diff options
author | Chris Xiong <chirs241097@gmail.com> | 2016-09-15 23:46:17 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2016-09-15 23:46:17 +0800 |
commit | e12b8c202f92d1b154ed3d9cb5dc58c73aa08787 (patch) | |
tree | 7c32b9a03ef5d45f84344212756cb097971d9aee | |
parent | d62356c08e23c6971d2996866eb6bdf43000520b (diff) | |
download | QMidiPlayer-e12b8c202f92d1b154ed3d9cb5dc58c73aa08787.tar.xz |
Add a new visualization mode. Fix minor behavioral bugs.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | include/qmpcorepublic.hpp | 2 | ||||
-rw-r--r-- | qmidiplayer-desktop/qmpplugin.cpp | 12 | ||||
-rw-r--r-- | visualization/qmpvisualization.cpp | 110 | ||||
-rw-r--r-- | visualization/qmpvisualization.hpp | 3 |
6 files changed, 131 insertions, 6 deletions
@@ -1,3 +1,6 @@ +2016-09-15 0.8.3 alpha +Add a new visualization mode. Fix minor behavioral bugs. + 2016-09-15 0.8.2 alpha Fix FTBFS. Force Qt5 while building. diff --git a/debian/changelog b/debian/changelog index bf866f3..00d2283 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +qmidiplayer (0.8.3-0) UNRELEASED; urgency=low + + * New upstream release. + + -- chrisoft <chirs241097@gmail.com> Thu, 15 Sep 2016 23:42:20 +0800 + + qmidiplayer (0.8.1-1) UNRELEASED; urgency=low * New upstream release. diff --git a/include/qmpcorepublic.hpp b/include/qmpcorepublic.hpp index d578018..683bde9 100644 --- a/include/qmpcorepublic.hpp +++ b/include/qmpcorepublic.hpp @@ -69,6 +69,8 @@ class qmpPluginAPI virtual uint32_t getMaxPolyphone(); virtual uint32_t getCurrentTimeStamp(); virtual uint32_t getCurrentPlaybackPercentage(); + virtual int getChannelCC(int ch,int cc); + virtual int getChannelPreset(int ch); virtual void playerSeek(uint32_t percentage); virtual double getPitchBend(int ch); virtual bool getChannelMask(int ch); diff --git a/qmidiplayer-desktop/qmpplugin.cpp b/qmidiplayer-desktop/qmpplugin.cpp index 1ffd32c..7193ade 100644 --- a/qmidiplayer-desktop/qmpplugin.cpp +++ b/qmidiplayer-desktop/qmpplugin.cpp @@ -130,6 +130,18 @@ uint32_t qmpPluginAPI::getCurrentTimeStamp() {return qmw&&qmw->getPlayer()?qmw->getPlayer()->getTick():0;} uint32_t qmpPluginAPI::getCurrentPlaybackPercentage() {return qmw?qmw->getPlaybackPercentage():0;} +int qmpPluginAPI::getChannelCC(int ch,int cc) +{return qmw&&qmw->getPlayer()?qmw->getPlayer()->getCC(ch,cc):0;} +int qmpPluginAPI::getChannelPreset(int ch) +{ + int b,p;char nm[25],ret[33];ret[0]=0; + if(qmw&&qmw->getPlayer()) + { + qmw->getPlayer()->getChannelPreset(ch,&b,&p,nm); + return p; + } + return 0; +} void qmpPluginAPI::playerSeek(uint32_t percentage) {if(qmw)qmw->playerSeek(percentage);} double qmpPluginAPI::getPitchBend(int ch) diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp index 2ba091b..202b7b0 100644 --- a/visualization/qmpvisualization.cpp +++ b/visualization/qmpvisualization.cpp @@ -3,6 +3,7 @@ #include <cstring> #include <cmath> #include <algorithm> +#include <set> #include "qmpvisualization.hpp" int viewdist=100; @@ -11,7 +12,7 @@ int minnotelength=100; int noteappearance=1,showpiano=1,stairpiano=1,savevp=1,showlabel=1; int wwidth=800,wheight=600,wsupersample=1,wmultisample=0,showparticle=1; int horizontal=1,flat=0,osdpos=0,fontsize=16; -int fov=60,vsync=1,tfps=60; +int fov=60,vsync=1,tfps=60,usespectrum=0; DWORD chkrtint=0xFF999999; const char* minors="abebbbf c g d a e b f#c#g#d#a#"; const char* majors="CbGbDbAbEbBbF C G D A E B F#C#"; @@ -26,6 +27,15 @@ DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFEE99,0XFFFFFF99, 0XFF99FFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF, 0XFF9999FF,0XFFCC99FF,0XFFEE99FF,0XFFFF99EE}; +std::set<BYTE> sustaininst={16,17,18,19,20,21,22,23, + 40,41,42,43,44,45,48,49, + 50,51,52,53,54,56,57,58, + 59,60,61,62,63,64,65,66, + 67,68,69,70,71,72,73,74, + 75,76,77,78,79,80,81,82, + 83,84,85,86,87,89,90,91, + 92,93,94,95,97,101,109,110,111}; + bool cmp(MidiVisualEvent* a,MidiVisualEvent* b) { if(a->tcs<b->tcs)return true;if(a->tcs>b->tcs)return false; @@ -73,6 +83,7 @@ void qmpVisualization::showThread() notestretch=api->getOptionInt("Visualization/notestretch"); minnotelength=api->getOptionInt("Visualization/minnotelen"); chkrtint=api->getOptionUint("Visualization/chkrtint"); + usespectrum=api->getOptionBool("Visualization/usespectrum"); for(int i=0;i<16;++i) { accolors[i]=api->getOptionUint("Visualization/chActiveColor"+std::to_string(i)); @@ -270,6 +281,7 @@ bool qmpVisualization::update() //printf("pos: %f %f %f\n",pos[0],pos[1],pos[2]); //printf("rot: %f %f %f\n",rot[0],rot[1],rot[2]); double lpt=(double)notestretch/api->getDivision()/10.*(horizontal?0.25:1); + memcpy(lastnotestatus,notestatus,sizeof(notestatus)); memset(notestatus,0,sizeof(notestatus)); for(uint32_t i=elb;i<pool.size();++i) { @@ -293,7 +305,7 @@ bool qmpVisualization::update() } if(showparticle&&!horizontal) { - if(notestatus[pool[i]->ch][pool[i]->key]) + if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) { pss[pool[i]->ch][pool[i]->key]->startPS(); pss[pool[i]->ch][pool[i]->key]->setPos(smvec3d(0.756*((double)pool[i]->key-64)+.48,(stairpiano?(56-pool[i]->ch*7.):(64-pool[i]->ch*8.)),stairpiano*pool[i]->ch*2+0.1)); @@ -303,9 +315,36 @@ bool qmpVisualization::update() if(((double)pool[i]->tce-pool[i]->tcs)*lpt<minnotelength*(horizontal?0.0025:0.01)) {if(horizontal)a.x=((double)pool[i]->tcs-ctk)*lpt-minnotelength/100.-20; else a.z=((double)pool[i]->tcs-ctk)*lpt-minnotelength/100.+stairpiano*pool[i]->ch*2;} + if(usespectrum) + { + if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) + spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); + } + else drawCube(a,b,SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))),0); } } + if(usespectrum&&playing) + for(int i=0;i<16;++i)for(int j=0;j<128;++j) + { + if(sustaininst.find(api->getChannelPreset(i))!=sustaininst.end()) + { + if(!notestatus[i][j]&&spectra[i][j]) + spectra[i][j]=.95*spectra[i][j]; + }else if(spectra[i][j])spectra[i][j]=.95*spectra[i][j]; + if(spectrar[i][j]<spectra[i][j]*0.9)spectrar[i][j]+=spectra[i][j]*0.2; + else spectrar[i][j]=spectra[i][j]; + if(spectrar[i][j]) + { + smvec3d a(0.63*((double)j-64+api->getPitchBend(i))+.1, + (stairpiano?(56-i*7.):(64-i*8.)), + spectrar[i][j]*1.2*(1+0.02*sin(sm->smGetTime()*32))+(stairpiano&&showpiano&&!horizontal)*i*2.); + smvec3d b(0.63*((double)j-64+api->getPitchBend(i))+.7, + (stairpiano?(56-i*7.):(64-i*8.))+.4, + (stairpiano&&showpiano&&!horizontal)*i*2.); + drawCube(a,b,SETA(iccolors[i],204),0); + } + } if(noteappearance)nebuf->drawBatch(); if(showpiano&&!horizontal) for(int i=0;i<16;++i) @@ -386,7 +425,12 @@ bool qmpVisualization::update() nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y;for(int j=0;j<4;++j) nq.v[j].col=SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))); - sm->smRenderQuad(&nq); + if(usespectrum) + { + if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) + spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); + } + else sm->smRenderQuad(&nq); } } while(pool.size()&&elb<pool.size()&&fabs((double)pool[elb]->tce-ctk)*lpt+wheight-nh>wheight)++elb; @@ -449,6 +493,30 @@ bool qmpVisualization::update() } sm->smRenderQuad(&q); } + if(usespectrum&&playing) + for(int i=0;i<16;++i)for(int j=0;j<128;++j) + { + if(sustaininst.find(api->getChannelPreset(i))!=sustaininst.end()) + { + if(!notestatus[i][j]&&spectra[i][j]) + spectra[i][j]=.95*spectra[i][j]; + }else if(spectra[i][j])spectra[i][j]=.95*spectra[i][j]; + if(spectrar[i][j]<spectra[i][j]*0.9)spectrar[i][j]+=spectra[i][j]*0.2; + else spectrar[i][j]=spectra[i][j]; + if(spectrar[i][j]) + { + smvec2d a((froffsets[12]*(j/12)+froffsets[j%12])*wwidth/2048.,spectrar[i][j]/-128.*(wheight-nh)*(1+0.02*sin(sm->smGetTime()*32))+wheight-nh); + smvec2d b(a.x+notew*0.9,lpt+wheight-nh); + uint32_t newkey=j+(int)floor(api->getPitchBend(i)); + double fpb=api->getPitchBend(i)-floor(api->getPitchBend(i)); + a.x=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wwidth/2048.+notew*fpb; + b.x=a.x+notew*0.9; + nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; + nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y;for(int j=0;j<4;++j) + nq.v[j].col=SETA(iccolors[i],204); + sm->smRenderQuad(&nq); + } + } } else { @@ -477,7 +545,11 @@ bool qmpVisualization::update() nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y;for(int j=0;j<4;++j) nq.v[j].col=SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))); - sm->smRenderQuad(&nq); + if(usespectrum) + { + if(notestatus[pool[i]->ch][pool[i]->key]&&!lastnotestatus[pool[i]->ch][pool[i]->key]) + spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); + }else sm->smRenderQuad(&nq); } } while(pool.size()&&elb<pool.size()&&fabs((double)pool[elb]->tce-ctk)*lpt+nh<0)++elb; @@ -541,6 +613,31 @@ bool qmpVisualization::update() for(int j=0;j<4;++j)q.v[j].y=wheight-q.v[j].y; sm->smRenderQuad(&q); } + if(usespectrum&&playing) + for(int i=0;i<16;++i)for(int j=0;j<128;++j) + { + if(sustaininst.find(api->getChannelPreset(i))!=sustaininst.end()) + { + if(!notestatus[i][j]&&spectra[i][j]) + spectra[i][j]=.95*spectra[i][j]; + }else if(spectra[i][j])spectra[i][j]=.95*spectra[i][j]; + if(spectrar[i][j]<spectra[i][j]*0.9)spectrar[i][j]+=spectra[i][j]*0.2; + else spectrar[i][j]=spectra[i][j]; + if(spectrar[i][j]) + { + smvec2d a(spectrar[i][j]/128.*(wwidth-nh)*(1+0.02*sin(sm->smGetTime()*32))+nh,(froffsets[12]*(j/12)+froffsets[j%12])*wheight/2048.); + smvec2d b(nh,a.y+notew*0.9); + uint32_t newkey=j+(int)floor(api->getPitchBend(i)); + double fpb=api->getPitchBend(pool[i]->ch)-floor(api->getPitchBend(pool[i]->ch)); + a.y=(froffsets[12]*(newkey/12)+froffsets[newkey%12])*wheight/2048.+notew*fpb; + b.y=a.y+notew*0.9; + a.y=wheight-a.y;b.y=wheight-b.y; + nq.v[0].x=nq.v[3].x=a.x;nq.v[0].y=nq.v[1].y=a.y; + nq.v[1].x=nq.v[2].x=b.x;nq.v[2].y=nq.v[3].y=b.y;for(int j=0;j<4;++j) + nq.v[j].col=SETA(iccolors[i],204); + sm->smRenderQuad(&nq); + } + } } if(playing)ctk+=(int)(1e6/(api->getRawTempo()/api->getDivision())*sm->smGetDelta()); } @@ -612,7 +709,9 @@ void qmpVisualization::init() vi=new CDemoVisualization(this); h=new CMidiVisualHandler(this); closeh=new CloseHandler(this); - rendererTh=NULL; + rendererTh=NULL;playing=false; + memset(spectra,0,sizeof(spectra)); + memset(spectrar,0,sizeof(spectrar)); hvif=api->registerVisualizationIntf(vi); herif=api->registerEventReaderIntf(cb,NULL); hehif=api->registerEventHandlerIntf(hcb,NULL); @@ -623,6 +722,7 @@ void qmpVisualization::init() api->registerOptionBool("Visualization-Appearance","Show Particles","Visualization/showparticle",true); api->registerOptionBool("Visualization-Appearance","Horizontal Visualization","Visualization/horizontal",false); api->registerOptionBool("Visualization-Appearance","2D Visualization","Visualization/flat",false); + api->registerOptionBool("Visualization-Appearance","Use spectrum instead of piano roll","Visualization/usespectrum",false); api->registerOptionBool("Visualization-Video","Enable VSync","Visualization/vsync",true); api->registerOptionBool("Visualization-Video","Save Viewport","Visualization/savevp",true); api->registerOptionInt("Visualization-Video","Window Width","Visualization/wwidth",320,3200,800); diff --git a/visualization/qmpvisualization.hpp b/visualization/qmpvisualization.hpp index 76cfee2..21339b5 100644 --- a/visualization/qmpvisualization.hpp +++ b/visualization/qmpvisualization.hpp @@ -59,7 +59,8 @@ class qmpVisualization:public qmpPluginIntf double etps; bool shouldclose,playing; int hvif,herif,hehif; - int traveld[16][128];bool notestatus[16][128]; + int traveld[16][128];bool notestatus[16][128],lastnotestatus[16][128]; + int spectra[16][128],spectrar[16][128]; void drawCube(smvec3d a,smvec3d b,DWORD col,SMTEX tex); void showThread(); public: |