aboutsummaryrefslogtreecommitdiff
path: root/visualization
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2016-09-15 23:46:17 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2016-09-15 23:46:17 +0800
commite12b8c202f92d1b154ed3d9cb5dc58c73aa08787 (patch)
tree7c32b9a03ef5d45f84344212756cb097971d9aee /visualization
parentd62356c08e23c6971d2996866eb6bdf43000520b (diff)
downloadQMidiPlayer-e12b8c202f92d1b154ed3d9cb5dc58c73aa08787.tar.xz
Add a new visualization mode. Fix minor behavioral bugs.
Diffstat (limited to 'visualization')
-rw-r--r--visualization/qmpvisualization.cpp110
-rw-r--r--visualization/qmpvisualization.hpp3
2 files changed, 107 insertions, 6 deletions
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: