diff options
author | Chris Xiong <chirs241097@gmail.com> | 2020-05-12 00:58:40 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2020-05-12 00:58:40 +0800 |
commit | a7407edaf81c685d4a389785a405a53a5de4b148 (patch) | |
tree | e6e4f2d85f2172c94ac83a6e8f01e1e90a78ede9 /core/qmpmidiplay.cpp | |
parent | 437b7b16c322a8e53ac55a5f831098494d9a7073 (diff) | |
download | QMidiPlayer-a7407edaf81c685d4a389785a405a53a5de4b148.tar.xz |
Format EVERYTHING.
Hopefully this will make the source code less horrendous and actually
readable.
The command used was:
```
astyle --suffix=none --style=allman --attach-extern-c --attach-closing-while --indent-switches --indent-after-parens --pad-oper --pad-header --unpad-paren --align-pointer=name --recursive './*.cpp,*.hpp'
```
Diffstat (limited to 'core/qmpmidiplay.cpp')
-rw-r--r-- | core/qmpmidiplay.cpp | 1157 |
1 files changed, 663 insertions, 494 deletions
diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp index a354d6e..c987e01 100644 --- a/core/qmpmidiplay.cpp +++ b/core/qmpmidiplay.cpp @@ -9,609 +9,778 @@ #include <windows.h> uint64_t pf; #endif -CMidiPlayer* CMidiPlayer::ref=nullptr; +CMidiPlayer *CMidiPlayer::ref = nullptr; bool CMidiPlayer::processEvent(const SEvent *e) { - SEvent fe(*e); - fe.flags&=0xfe; - if(tceptr>=eorder.size()-1||getEvent(tceptr+1)->time>e->time) - fe.flags|=0x01; - for(int i=0;i<16;++i)if(eventHandlerCB[i]) - eventHandlerCB[i]->callBack((void*)&fe,eventHandlerCBuserdata[i]); - for(auto i=event_handlers.begin();i!=event_handlers.end();++i) - if(!std::get<2>(i->second)) - std::get<0>(i->second)((void*)e,std::get<1>(i->second)); - uint8_t ch=e->type&0x0F; - if((e->type&0xF0)<0xF0) - levtt[ch]=std::chrono::system_clock::now(); - switch(e->type&0xF0) - { - case 0x80://Note off - return true; - case 0x90://Note on - if((mute>>ch)&1&&e->p2)return false;//muted - if(solo&&!((solo>>ch)&1)&&e->p2)return false;//excluded by solo flags - return true; - case 0xB0://CC - if(e->p1==100)rpnid[ch]=e->p2; - if(e->p1==6)rpnval[ch]=e->p2; - if(~rpnid[ch]&&~rpnval[ch]) - { - if(rpnid[ch]==0) - { - mididev[mappedoutput[ch]].dev->rpnMessage(ch,0,rpnval[ch]<<7); - pbr[ch]=rpnval[ch]; - } - rpnid[ch]=rpnval[ch]=-1; - } - chstatus[ch][e->p1]=e->p2; - return true; - case 0xC0://PC - chstatus[ch][128]=e->p1; - return true; - case 0xE0://PW - pbv[ch]=(e->p1|(e->p2<<7))&0x3FFF; - return true; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - { - ctempo=0; + SEvent fe(*e); + fe.flags &= 0xfe; + if (tceptr >= eorder.size() - 1 || getEvent(tceptr + 1)->time > e->time) + fe.flags |= 0x01; + for (int i = 0; i < 16; ++i) + if (eventHandlerCB[i]) + eventHandlerCB[i]->callBack((void *)&fe, eventHandlerCBuserdata[i]); + for (auto i = event_handlers.begin(); i != event_handlers.end(); ++i) + if (!std::get<2>(i->second)) + std::get<0>(i->second)((void *)e, std::get<1>(i->second)); + uint8_t ch = e->type & 0x0F; + if ((e->type & 0xF0) < 0xF0) + levtt[ch] = std::chrono::system_clock::now(); + switch (e->type & 0xF0) + { + case 0x80://Note off + return true; + case 0x90://Note on + if ((mute >> ch) & 1 && e->p2) + return false; //muted + if (solo && !((solo >> ch) & 1) && e->p2) + return false; //excluded by solo flags + return true; + case 0xB0://CC + if (e->p1 == 100) + rpnid[ch] = e->p2; + if (e->p1 == 6) + rpnval[ch] = e->p2; + if (~rpnid[ch] && ~rpnval[ch]) + { + if (rpnid[ch] == 0) + { + mididev[mappedoutput[ch]].dev->rpnMessage(ch, 0, rpnval[ch] << 7); + pbr[ch] = rpnval[ch]; + } + rpnid[ch] = rpnval[ch] = -1; + } + chstatus[ch][e->p1] = e->p2; + return true; + case 0xC0://PC + chstatus[ch][128] = e->p1; + return true; + case 0xE0://PW + pbv[ch] = (e->p1 | (e->p2 << 7)) & 0x3FFF; + return true; + case 0xF0://Meta/SysEx + if ((e->type & 0x0F) == 0x0F) + { + switch (e->p1) + { + case 0x51: + { + ctempo = 0; #if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__)||defined(_WIN32) - std::string x(e->str); - std::reverse(x.begin(),x.end()); - memcpy(&ctempo,x.data(),3); + std::string x(e->str); + std::reverse(x.begin(), x.end()); + memcpy(&ctempo, x.data(), 3); #else - memcpy(&ctempo,e->str.data(),3); - ctempo>>=8; + memcpy(&ctempo, e->str.data(), 3); + ctempo >>= 8; #endif - dpt=ctempo*1000./divs; - ttime=std::chrono::high_resolution_clock::now(); - ttick=getTick(); - } - break; - case 0x58: - ctsn=(uint32_t)e->str[0]; - ctsd=1<<((uint32_t)e->str[1]); - break; - case 0x59: - if(e->str.length()==2) - cks=(e->str[0]<<8u)|e->str[1]; - break; - case 0x01:case 0x02:case 0x03: - case 0x04:case 0x05:case 0x06: - case 0x07: - //if(e->str)puts(e->str); - break; - } - } - if(((e->type&0x0F)==0x00||(e->type&0x0F)==07)&&sendSysEx) - for(auto& i:mididev) - if(i.refcnt) - i.dev->extendedMessage(uint32_t(e->str.length()),e->str.c_str()); - return false; - } - return false; + dpt = ctempo * 1000. / divs; + ttime = std::chrono::high_resolution_clock::now(); + ttick = getTick(); + } + break; + case 0x58: + ctsn = (uint32_t)e->str[0]; + ctsd = 1 << ((uint32_t)e->str[1]); + break; + case 0x59: + if (e->str.length() == 2) + cks = (e->str[0] << 8u) | e->str[1]; + break; + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + //if(e->str)puts(e->str); + break; + } + } + if (((e->type & 0x0F) == 0x00 || (e->type & 0x0F) == 07) && sendSysEx) + for (auto &i : mididev) + if (i.refcnt) + i.dev->extendedMessage(uint32_t(e->str.length()), e->str.c_str()); + return false; + } + return false; } void CMidiPlayer::processEventStub(const SEvent *e) { - switch(e->type&0xF0) - { - case 0xB0://CC - if(e->p1==100)rpnid[e->type&0x0F]=e->p2; - if(e->p1==6)rpnval[e->type&0x0F]=e->p2; - if(~rpnid[e->type&0x0F]&&~rpnval[e->type&0x0F]) - { - if(rpnid[e->type&0x0F]==0)ccc[e->type&0x0F][134]=rpnval[e->type&0x0F]; - rpnval[e->type&0x0F]=-1; - } - ccc[e->type&0x0F][e->p1]=e->p2; - break; - case 0xC0://PC - ccc[e->type&0x0F][128]=e->p1; - break; - case 0xD0://CP - ccc[e->type&0x0F][129]=e->p1; - break; - case 0xE0://PW - ccc[e->type&0x0F][130]=(e->p1|(e->p2<<7))&0x3FFF; - break; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - { - ctempo=0; + switch (e->type & 0xF0) + { + case 0xB0://CC + if (e->p1 == 100) + rpnid[e->type & 0x0F] = e->p2; + if (e->p1 == 6) + rpnval[e->type & 0x0F] = e->p2; + if (~rpnid[e->type & 0x0F] && ~rpnval[e->type & 0x0F]) + { + if (rpnid[e->type & 0x0F] == 0) + ccc[e->type & 0x0F][134] = rpnval[e->type & 0x0F]; + rpnval[e->type & 0x0F] = -1; + } + ccc[e->type & 0x0F][e->p1] = e->p2; + break; + case 0xC0://PC + ccc[e->type & 0x0F][128] = e->p1; + break; + case 0xD0://CP + ccc[e->type & 0x0F][129] = e->p1; + break; + case 0xE0://PW + ccc[e->type & 0x0F][130] = (e->p1 | (e->p2 << 7)) & 0x3FFF; + break; + case 0xF0://Meta/SysEx + if ((e->type & 0x0F) == 0x0F) + { + switch (e->p1) + { + case 0x51: + { + ctempo = 0; #if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__)||defined(_WIN32) - std::string x(e->str); - std::reverse(x.begin(),x.end()); - memcpy(&ctempo,x.data(),3); + std::string x(e->str); + std::reverse(x.begin(), x.end()); + memcpy(&ctempo, x.data(), 3); #else - memcpy(&ctempo,e->str.data(),3); - ctempo>>=8; + memcpy(&ctempo, e->str.data(), 3); + ctempo >>= 8; #endif - dpt=ctempo*1000./divs; - ccc[0][131]=ctempo; - } - break; - case 0x58: - ccc[0][132]=(e->str[0]<<24u)|(e->str[1]<<16u); - break; - case 0x59: - if(e->str.length()>=2) - ccc[0][133]=(e->str[0]<<8u)|e->str[1]; - break; - } - } - break; - } + dpt = ctempo * 1000. / divs; + ccc[0][131] = ctempo; + } + break; + case 0x58: + ccc[0][132] = (e->str[0] << 24u) | (e->str[1] << 16u); + break; + case 0x59: + if (e->str.length() >= 2) + ccc[0][133] = (e->str[0] << 8u) | e->str[1]; + break; + } + } + break; + } } #ifdef _WIN32 void w32usleep(uint64_t t) { - uint64_t st=0,ct=0; - timeBeginPeriod(1); - QueryPerformanceCounter((LARGE_INTEGER*)&st); - do{ - if(t>10000+(ct-st)*1000000/pf)Sleep((t-(ct-st)*1000000/pf)/2000); - else if(t>5000+(ct-st)*1000000/pf)Sleep(1); - else std::this_thread::yield(); - QueryPerformanceCounter((LARGE_INTEGER*)&ct); - }while((ct-st)*1000000<t*pf); - timeEndPeriod(1); + uint64_t st = 0, ct = 0; + timeBeginPeriod(1); + QueryPerformanceCounter((LARGE_INTEGER *)&st); + do + { + if (t > 10000 + (ct - st) * 1000000 / pf) + Sleep((t - (ct - st) * 1000000 / pf) / 2000); + else if (t > 5000 + (ct - st) * 1000000 / pf) + Sleep(1); + else + std::this_thread::yield(); + QueryPerformanceCounter((LARGE_INTEGER *)&ct); + } while ((ct - st) * 1000000 < t * pf); + timeEndPeriod(1); } #endif -SEvent* CMidiPlayer::getEvent(uint32_t id) +SEvent *CMidiPlayer::getEvent(uint32_t id) { - size_t t=eorder[id].first,e=eorder[id].second; - return &midiFile->tracks[t].eventList[e]; + size_t t = eorder[id].first, e = eorder[id].second; + return &midiFile->tracks[t].eventList[e]; } void CMidiPlayer::prePlayInit() { - playerPanic(true); - for(size_t i=0;i<mididev.size();++i) - if(mididev[i].refcnt) - mididev[i].dev->reset(0xFF); + playerPanic(true); + for (size_t i = 0; i < mididev.size(); ++i) + if (mididev[i].refcnt) + mididev[i].dev->reset(0xFF); } void CMidiPlayer::playEvents() { - static uint32_t _lrtick;_lrtick=0; - ttick=getEvent(0)->time;ttime=std::chrono::high_resolution_clock::now(); - for(ct=getEvent(0)->time;tceptr<ecnt;) - { - using namespace std::chrono; - while(tcpaused)std::this_thread::sleep_for(milliseconds(100)); - if(resumed){ - resumed=false; - ct=getEvent(tceptr)->time; - ttick=getTick(); - ttime=high_resolution_clock::now(); - continue; - } - high_resolution_clock::time_point b=high_resolution_clock::now(); - if(getTick()-_lrtick>divs){ - _lrtick=getTick(); - //double _dt=(getTick()-ttick)*dpt-duration_cast<nanoseconds>((b-ttime)).count(); - //<0: slower than expected, >0: faster than expected - //fprintf(stderr,"@ tick %u, dtime %.6fus",getTick(),_dt/1000.); - } - for(;!tcstop&&midiReaders&&tceptr<ecnt&&ct==getEvent(tceptr)->time;++tceptr) - { - if(processEvent(getEvent(tceptr))) - { - SEvent* e=getEvent(tceptr); - mididev[mappedoutput[e->type&0x0F]].dev->basicMessage(e->type,e->p1,e->p2); - } - for(auto i=event_handlers.begin();i!=event_handlers.end();++i) - if(std::get<2>(i->second)) - std::get<0>(i->second)((void*)getEvent(tceptr),std::get<1>(i->second)); - } - if(tcstop||!midiReaders||tceptr>=ecnt)break; - high_resolution_clock::time_point a=high_resolution_clock::now(); - auto sendtime=a-b; - if(sendtime.count()<(getEvent(tceptr)->time-ct)*dpt) - { - double ns_sleep=(getEvent(tceptr)->time-ct)*dpt-sendtime.count(); - double correction=(getTick()-ttick)*dpt-(b-ttime).count(); - if(correction>0)correction=0; + static uint32_t _lrtick; + _lrtick = 0; + ttick = getEvent(0)->time; + ttime = std::chrono::high_resolution_clock::now(); + for (ct = getEvent(0)->time; tceptr < ecnt;) + { + using namespace std::chrono; + while (tcpaused) + std::this_thread::sleep_for(milliseconds(100)); + if (resumed) + { + resumed = false; + ct = getEvent(tceptr)->time; + ttick = getTick(); + ttime = high_resolution_clock::now(); + continue; + } + high_resolution_clock::time_point b = high_resolution_clock::now(); + if (getTick() - _lrtick > divs) + { + _lrtick = getTick(); + //double _dt=(getTick()-ttick)*dpt-duration_cast<nanoseconds>((b-ttime)).count(); + //<0: slower than expected, >0: faster than expected + //fprintf(stderr,"@ tick %u, dtime %.6fus",getTick(),_dt/1000.); + } + for (; !tcstop && midiReaders && tceptr < ecnt && ct == getEvent(tceptr)->time; ++tceptr) + { + if (processEvent(getEvent(tceptr))) + { + SEvent *e = getEvent(tceptr); + mididev[mappedoutput[e->type & 0x0F]].dev->basicMessage(e->type, e->p1, e->p2); + } + for (auto i = event_handlers.begin(); i != event_handlers.end(); ++i) + if (std::get<2>(i->second)) + std::get<0>(i->second)((void *)getEvent(tceptr), std::get<1>(i->second)); + } + if (tcstop || !midiReaders || tceptr >= ecnt) + break; + high_resolution_clock::time_point a = high_resolution_clock::now(); + auto sendtime = a - b; + if (sendtime.count() < (getEvent(tceptr)->time - ct)*dpt) + { + double ns_sleep = (getEvent(tceptr)->time - ct) * dpt - sendtime.count(); + double correction = (getTick() - ttick) * dpt - (b - ttime).count(); + if (correction > 0) + correction = 0; #ifdef _WIN32 - w32usleep((uint64_t)(((getEvent(tceptr)->time-ct)*dpt-sendtime.count())/1000)); + w32usleep((uint64_t)(((getEvent(tceptr)->time - ct)*dpt - sendtime.count()) / 1000)); #else - std::this_thread::sleep_for(std::chrono::nanoseconds((uint64_t)(ns_sleep+correction))); + std::this_thread::sleep_for(std::chrono::nanoseconds((uint64_t)(ns_sleep + correction))); #endif - } - if(tcstop||!midiReaders)break; - ct=getEvent(tceptr)->time; - } - if(tceptr>=ecnt) - finished=1; + } + if (tcstop || !midiReaders) + break; + ct = getEvent(tceptr)->time; + } + if (tceptr >= ecnt) + finished = 1; } void CMidiPlayer::fileTimer1Pass() { - ftime=.0;ctempo=0x7A120;dpt=ctempo*1000./divs; - for(uint32_t eptr=0,ct=getEvent(0)->time;eptr<ecnt;) - { - while(eptr<ecnt&&ct==getEvent(eptr)->time) - processEventStub(getEvent(eptr++)); - if(eptr>=ecnt)break; - ftime+=(getEvent(eptr)->time-ct)*dpt/1e9; - ct=getEvent(eptr)->time; - } + ftime = .0; + ctempo = 0x7A120; + dpt = ctempo * 1000. / divs; + for (uint32_t eptr = 0, ct = getEvent(0)->time; eptr < ecnt;) + { + while (eptr < ecnt && ct == getEvent(eptr)->time) + processEventStub(getEvent(eptr++)); + if (eptr >= ecnt) + break; + ftime += (getEvent(eptr)->time - ct) * dpt / 1e9; + ct = getEvent(eptr)->time; + } } void CMidiPlayer::fileTimer2Pass() { - double ctime=.0;uint32_t c=1;ctempo=0x7A120;dpt=ctempo*1000./divs; - memset(stamps,0,sizeof(stamps));memset(ccstamps,0,sizeof(ccstamps)); - memset(ccc,0,sizeof(ccc));memset(rpnid,0xFF,sizeof(rpnid));memset(rpnval,0xFF,sizeof(rpnval)); - for(int i=0;i<16;++i) - { - memset(ccc[i],0xFF,128*sizeof(uint32_t)); - ccc[i][131]=ctempo;ccc[i][132]=0x04021808; - ccc[i][133]=0;ccc[i][134]=2; - } - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[0][i][j]=ccc[i][j]; - for(uint32_t eptr=0,ct=getEvent(0)->time;eptr<ecnt;) - { - while(eptr<ecnt&&ct==getEvent(eptr)->time) - processEventStub(getEvent(eptr++)); - if(eptr>=ecnt)break; - ctime+=(getEvent(eptr)->time-ct)*dpt/1e9; - while(ctime>ftime*c/100.) - { - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[c][i][j]=ccc[i][j]; - stamps[c++]=eptr; - if(c>100)break; - } - ct=getEvent(eptr)->time; - } - while(c<101) - { - for(int i=0;i<16;++i)for(int j=0;j<135;++j) - ccstamps[c][i][j]=ccc[i][j]; - stamps[c++]=ecnt; - } + double ctime = .0; + uint32_t c = 1; + ctempo = 0x7A120; + dpt = ctempo * 1000. / divs; + memset(stamps, 0, sizeof(stamps)); + memset(ccstamps, 0, sizeof(ccstamps)); + memset(ccc, 0, sizeof(ccc)); + memset(rpnid, 0xFF, sizeof(rpnid)); + memset(rpnval, 0xFF, sizeof(rpnval)); + for (int i = 0; i < 16; ++i) + { + memset(ccc[i], 0xFF, 128 * sizeof(uint32_t)); + ccc[i][131] = ctempo; + ccc[i][132] = 0x04021808; + ccc[i][133] = 0; + ccc[i][134] = 2; + } + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 135; ++j) + ccstamps[0][i][j] = ccc[i][j]; + for (uint32_t eptr = 0, ct = getEvent(0)->time; eptr < ecnt;) + { + while (eptr < ecnt && ct == getEvent(eptr)->time) + processEventStub(getEvent(eptr++)); + if (eptr >= ecnt) + break; + ctime += (getEvent(eptr)->time - ct) * dpt / 1e9; + while (ctime > ftime * c / 100.) + { + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 135; ++j) + ccstamps[c][i][j] = ccc[i][j]; + stamps[c++] = eptr; + if (c > 100) + break; + } + ct = getEvent(eptr)->time; + } + while (c < 101) + { + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 135; ++j) + ccstamps[c][i][j] = ccc[i][j]; + stamps[c++] = ecnt; + } } CMidiPlayer::CMidiPlayer() { - midiReaders=new CMidiFileReaderCollection(); - resumed=false;midiFile=nullptr; - waitvoice=true; - event_handlers_id=event_read_handlers_id=file_read_finish_hooks_id=0; - memset(eventHandlerCB,0,sizeof(eventHandlerCB)); - memset(eventHandlerCBuserdata,0,sizeof(eventHandlerCBuserdata)); - memset(eventReaderCB,0,sizeof(eventReaderCB)); - memset(eventReaderCBuserdata,0,sizeof(eventReaderCBuserdata)); - memset(fileReadFinishCB,0,sizeof(fileReadFinishCB)); - memset(fileReadFinishCBuserdata,0,sizeof(fileReadFinishCBuserdata)); - memset(mappedoutput,0xff,sizeof(mappedoutput)); - memset(chstatus,0,sizeof(chstatus)); - for(int i=0;i<16;++i) - memset(chstatus[i],0xff,128*sizeof(uint8_t)); + midiReaders = new CMidiFileReaderCollection(); + resumed = false; + midiFile = nullptr; + waitvoice = true; + event_handlers_id = event_read_handlers_id = file_read_finish_hooks_id = 0; + memset(eventHandlerCB, 0, sizeof(eventHandlerCB)); + memset(eventHandlerCBuserdata, 0, sizeof(eventHandlerCBuserdata)); + memset(eventReaderCB, 0, sizeof(eventReaderCB)); + memset(eventReaderCBuserdata, 0, sizeof(eventReaderCBuserdata)); + memset(fileReadFinishCB, 0, sizeof(fileReadFinishCB)); + memset(fileReadFinishCBuserdata, 0, sizeof(fileReadFinishCBuserdata)); + memset(mappedoutput, 0xff, sizeof(mappedoutput)); + memset(chstatus, 0, sizeof(chstatus)); + for (int i = 0; i < 16; ++i) + memset(chstatus[i], 0xff, 128 * sizeof(uint8_t)); #ifdef _WIN32 - QueryPerformanceFrequency((LARGE_INTEGER*)&pf); + QueryPerformanceFrequency((LARGE_INTEGER *)&pf); #endif - ref=this; + ref = this; } CMidiPlayer::~CMidiPlayer() { - if(midiFile)delete midiFile;delete midiReaders; + if (midiFile) + delete midiFile; + delete midiReaders; } void CMidiPlayer::playerPanic(bool reset) { - for(auto& i:mididev) - if(i.refcnt) - { - for(uint8_t j=0;j<16;++j) - reset?i.dev->reset(j):i.dev->panic(j); - } -} -bool CMidiPlayer::playerLoadFile(const char* fn) -{ - notes=0;if(midiFile)delete midiFile; - midiFile=midiReaders->readFile(fn); - if(!midiFile||!midiFile->valid)return false; - divs=midiFile->divs;maxtk=ecnt=0; - for(CMidiTrack& i:midiFile->tracks) - { - ecnt+=i.eventList.size(); - if(i.eventList.size()) - maxtk=std::max(maxtk,i.eventList.back().time); - } - for(int i=0;i<16;++i)if(fileReadFinishCB[i]) - fileReadFinishCB[i]->callBack(nullptr,fileReadFinishCBuserdata[i]); - for(auto i=file_read_finish_hooks.begin();i!=file_read_finish_hooks.end();++i) - i->second.first(nullptr,i->second.second); - eorder.clear(); - for(size_t i=0;i<midiFile->tracks.size();++i) - for(size_t j=0;j<midiFile->tracks[i].eventList.size();++j) - eorder.push_back(std::make_pair(i,j)); - std::sort(eorder.begin(),eorder.end(), - [this](std::pair<size_t,size_t> &a,std::pair<size_t,size_t> &b)->bool{ - return midiFile->tracks[a.first].eventList[a.second]< - midiFile->tracks[b.first].eventList[b.second]; - } - ); - fileTimer1Pass(); - fileTimer2Pass(); - return true; + for (auto &i : mididev) + if (i.refcnt) + { + for (uint8_t j = 0; j < 16; ++j) + reset ? i.dev->reset(j) : i.dev->panic(j); + } +} +bool CMidiPlayer::playerLoadFile(const char *fn) +{ + notes = 0; + if (midiFile) + delete midiFile; + midiFile = midiReaders->readFile(fn); + if (!midiFile || !midiFile->valid) + return false; + divs = midiFile->divs; + maxtk = ecnt = 0; + for (CMidiTrack &i : midiFile->tracks) + { + ecnt += i.eventList.size(); + if (i.eventList.size()) + maxtk = std::max(maxtk, i.eventList.back().time); + } + for (int i = 0; i < 16; ++i) + if (fileReadFinishCB[i]) + fileReadFinishCB[i]->callBack(nullptr, fileReadFinishCBuserdata[i]); + for (auto i = file_read_finish_hooks.begin(); i != file_read_finish_hooks.end(); ++i) + i->second.first(nullptr, i->second.second); + eorder.clear(); + for (size_t i = 0; i < midiFile->tracks.size(); ++i) + for (size_t j = 0; j < midiFile->tracks[i].eventList.size(); ++j) + eorder.push_back(std::make_pair(i, j)); + std::sort(eorder.begin(), eorder.end(), + [this](std::pair<size_t, size_t> &a, std::pair<size_t, size_t> &b)->bool + { + return midiFile->tracks[a.first].eventList[a.second] < + midiFile->tracks[b.first].eventList[b.second]; + }); + fileTimer1Pass(); + fileTimer2Pass(); + return true; } void CMidiPlayer::playerInit() { - ctempo=0x7A120;ctsn=4;ctsd=4;cks=0;dpt=ctempo*1000./divs; - tceptr=0;tcstop=false;tcpaused=0;finished=0;mute=solo=0; - for(int i=0;i<16;++i)pbr[i]=2,pbv[i]=8192; - sendSysEx=true;memset(rpnid,0xFF,sizeof(rpnid));memset(rpnval,0xFF,sizeof(rpnval)); - memset(chstatus,0,sizeof(chstatus)); - for(int i=0;i<16;++i) - memset(chstatus[i],0xff,128*sizeof(uint8_t)); + ctempo = 0x7A120; + ctsn = 4; + ctsd = 4; + cks = 0; + dpt = ctempo * 1000. / divs; + tceptr = 0; + tcstop = false; + tcpaused = 0; + finished = 0; + mute = solo = 0; + for (int i = 0; i < 16; ++i) + pbr[i] = 2, pbv[i] = 8192; + sendSysEx = true; + memset(rpnid, 0xFF, sizeof(rpnid)); + memset(rpnval, 0xFF, sizeof(rpnval)); + memset(chstatus, 0, sizeof(chstatus)); + for (int i = 0; i < 16; ++i) + memset(chstatus[i], 0xff, 128 * sizeof(uint8_t)); } void CMidiPlayer::playerDeinit() { - tceptr=0;tcstop=true;tcpaused=0; - delete midiFile;midiFile=nullptr; + tceptr = 0; + tcstop = true; + tcpaused = 0; + delete midiFile; + midiFile = nullptr; } void CMidiPlayer::playerThread() { - prePlayInit(); - playEvents(); + prePlayInit(); + playEvents(); } -void CMidiPlayer::sendSysX(bool send){sendSysEx=send;} -uint32_t CMidiPlayer::getStamp(int id){return stamps[id];} -uint32_t CMidiPlayer::getTCeptr(){return tceptr;} -void CMidiPlayer::setTCeptr(uint32_t ep,uint32_t st) -{ - resumed=true; - if(ep==ecnt)tcstop=true;else tceptr=ep; - for(int i=0;i<16;++i) - { - qmpMidiOutDevice* dest=mididev[mappedoutput[i]].dev; - for(int j=0;j<120;++j) - { - if(~ccstamps[st][i][j]) - { - dest->basicMessage(0xB0|i,j,ccstamps[st][i][j]); - chstatus[i][j]=ccstamps[st][i][j]; - } - } - dest->basicMessage(0xC0|i,ccstamps[st][i][128],0); - chstatus[i][128]=ccstamps[st][i][128]; - dest->rpnMessage(i,0,ccstamps[st][i][134]<<7); - pbr[i]=ccstamps[st][i][134]; - ctempo=ccstamps[st][0][131];dpt=ctempo*1000./divs; - ctsn=ccstamps[st][0][132]>>24;ctsd=1<<((ccstamps[st][0][132]>>16)&0xFF); - cks=ccstamps[st][0][133]; - } -} -double CMidiPlayer::getFtime(){return ftime;} -void CMidiPlayer::getCurrentTimeSignature(int *n,int *d){*n=ctsn;*d=ctsd;} -int CMidiPlayer::getCurrentKeySignature(){return cks;} -uint32_t CMidiPlayer::getFileNoteCount(){return notes;} -uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->std:0;} -const char* CMidiPlayer::getTitle(){return midiFile?midiFile->title:"";} -const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->copyright:"";} -double CMidiPlayer::getTempo(){return 60./(ctempo/1e6);} -uint32_t CMidiPlayer::getTick(){return ct;} -uint32_t CMidiPlayer::getRawTempo(){return ctempo;} -uint32_t CMidiPlayer::getDivision(){return divs;} -uint32_t CMidiPlayer::getMaxTick(){return maxtk;} -double CMidiPlayer::getPitchBend(int ch){return((int)pbv[ch]-8192)/8192.*pbr[ch];} -double CMidiPlayer::getPitchBendRaw(int ch,uint32_t *pb,uint32_t *pbr) -{ - if(pb)*pb=this->pbv[ch]; - if(pbr)*pbr=this->pbr[ch]; -} -uint32_t CMidiPlayer::getTCpaused(){return tcpaused;} -void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;} -uint32_t CMidiPlayer::isFinished(){return finished;} -bool CMidiPlayer::stopFlag(){return tcstop;} -void CMidiPlayer::setResumed(){resumed=true;} +void CMidiPlayer::sendSysX(bool send) +{ + sendSysEx = send; +} +uint32_t CMidiPlayer::getStamp(int id) +{ + return stamps[id]; +} +uint32_t CMidiPlayer::getTCeptr() +{ + return tceptr; +} +void CMidiPlayer::setTCeptr(uint32_t ep, uint32_t st) +{ + resumed = true; + if (ep == ecnt) + tcstop = true; + else tceptr = ep; + for (int i = 0; i < 16; ++i) + { + qmpMidiOutDevice *dest = mididev[mappedoutput[i]].dev; + for (int j = 0; j < 120; ++j) + { + if (~ccstamps[st][i][j]) + { + dest->basicMessage(0xB0 | i, j, ccstamps[st][i][j]); + chstatus[i][j] = ccstamps[st][i][j]; + } + } + dest->basicMessage(0xC0 | i, ccstamps[st][i][128], 0); + chstatus[i][128] = ccstamps[st][i][128]; + dest->rpnMessage(i, 0, ccstamps[st][i][134] << 7); + pbr[i] = ccstamps[st][i][134]; + ctempo = ccstamps[st][0][131]; + dpt = ctempo * 1000. / divs; + ctsn = ccstamps[st][0][132] >> 24; + ctsd = 1 << ((ccstamps[st][0][132] >> 16) & 0xFF); + cks = ccstamps[st][0][133]; + } +} +double CMidiPlayer::getFtime() +{ + return ftime; +} +void CMidiPlayer::getCurrentTimeSignature(int *n, int *d) +{ + *n = ctsn; + *d = ctsd; +} +int CMidiPlayer::getCurrentKeySignature() +{ + return cks; +} +uint32_t CMidiPlayer::getFileNoteCount() +{ + return notes; +} +uint32_t CMidiPlayer::getFileStandard() +{ + return midiFile ? midiFile->std : 0; +} +const char *CMidiPlayer::getTitle() +{ + return midiFile ? midiFile->title : ""; +} +const char *CMidiPlayer::getCopyright() +{ + return midiFile ? midiFile->copyright : ""; +} +double CMidiPlayer::getTempo() +{ + return 60. / (ctempo / 1e6); +} +uint32_t CMidiPlayer::getTick() +{ + return ct; +} +uint32_t CMidiPlayer::getRawTempo() +{ + return ctempo; +} +uint32_t CMidiPlayer::getDivision() +{ + return divs; +} +uint32_t CMidiPlayer::getMaxTick() +{ + return maxtk; +} +double CMidiPlayer::getPitchBend(int ch) +{ + return ((int)pbv[ch] - 8192) / 8192.*pbr[ch]; +} +double CMidiPlayer::getPitchBendRaw(int ch, uint32_t *pb, uint32_t *pbr) +{ + if (pb) + *pb = this->pbv[ch]; + if (pbr) + *pbr = this->pbr[ch]; +} +uint32_t CMidiPlayer::getTCpaused() +{ + return tcpaused; +} +void CMidiPlayer::setTCpaused(uint32_t ps) +{ + tcpaused = ps; +} +uint32_t CMidiPlayer::isFinished() +{ + return finished; +} +bool CMidiPlayer::stopFlag() +{ + return tcstop; +} +void CMidiPlayer::setResumed() +{ + resumed = true; +} -void CMidiPlayer::setChannelPreset(int ch,int b,int p) +void CMidiPlayer::setChannelPreset(int ch, int b, int p) { - chstatus[ch][128]=p; - chstatus[ch][0]=b>>7;chstatus[ch][32]=b&0x7F; - qmpMidiOutDevice* d=mididev[mappedoutput[ch]].dev; - d->basicMessage(0xB0|ch,0x00,b>>7); - d->basicMessage(0xB0|ch,0x20,b&0x7F); - d->basicMessage(0xC0|ch,p,0); + chstatus[ch][128] = p; + chstatus[ch][0] = b >> 7; + chstatus[ch][32] = b & 0x7F; + qmpMidiOutDevice *d = mididev[mappedoutput[ch]].dev; + d->basicMessage(0xB0 | ch, 0x00, b >> 7); + d->basicMessage(0xB0 | ch, 0x20, b & 0x7F); + d->basicMessage(0xC0 | ch, p, 0); } void CMidiPlayer::dumpFile() { - if(!midiFile)return; - for(CMidiTrack &i:midiFile->tracks) - for(SEvent &j:i.eventList) - if(j.str.length()) - printf("type %x #%d @%d p1 %d p2 %d str %s\n",j.type, - j.iid,j.time,j.p1,j.p2,j.str.c_str()); - else - printf("type %x #%d @%d p1 %d p2 %d\n",j.type,j.iid, - j.time,j.p1,j.p2); + if (!midiFile) + return; + for (CMidiTrack &i : midiFile->tracks) + for (SEvent &j : i.eventList) + if (j.str.length()) + printf("type %x #%d @%d p1 %d p2 %d str %s\n", j.type, + j.iid, j.time, j.p1, j.p2, j.str.c_str()); + else + printf("type %x #%d @%d p1 %d p2 %d\n", j.type, j.iid, + j.time, j.p1, j.p2); } //16MSB..LSB1 void CMidiPlayer::setBit(uint16_t &n, uint16_t bn, uint16_t b) -{n^=(((~b)+1)^n)&(1<<bn);} -void CMidiPlayer::setMute(int ch,bool m) -{setBit(mute,ch,m?1:0);} -void CMidiPlayer::setSolo(int ch,bool s) -{setBit(solo,ch,s?1:0);} +{ + n ^= (((~b) + 1)^n) & (1 << bn); +} +void CMidiPlayer::setMute(int ch, bool m) +{ + setBit(mute, ch, m ? 1 : 0); +} +void CMidiPlayer::setSolo(int ch, bool s) +{ + setBit(solo, ch, s ? 1 : 0); +} bool CMidiPlayer::getChannelMask(int ch) -{return((mute>>ch)&1)||(solo&&!((solo>>ch)&1));} -uint16_t CMidiPlayer::getCC(int ch,int id) { - if(chstatus[ch][id]==0xff) - return getChannelOutputDevice(ch)->getInitialCCValue(uint8_t(id),uint8_t(ch)); - return chstatus[ch][id]; + return ((mute >> ch) & 1) || (solo && !((solo >> ch) & 1)); +} +uint16_t CMidiPlayer::getCC(int ch, int id) +{ + if (chstatus[ch][id] == 0xff) + return getChannelOutputDevice(ch)->getInitialCCValue(uint8_t(id), uint8_t(ch)); + return chstatus[ch][id]; } -void CMidiPlayer::setCC(int ch,int id,int val) +void CMidiPlayer::setCC(int ch, int id, int val) { - chstatus[ch][id]=val; - mididev[mappedoutput[ch]].dev->basicMessage(0xB0|ch,id,val); + chstatus[ch][id] = val; + mididev[mappedoutput[ch]].dev->basicMessage(0xB0 | ch, id, val); } -void CMidiPlayer::registerMidiOutDevice(qmpMidiOutDevice* dev,std::string name) +void CMidiPlayer::registerMidiOutDevice(qmpMidiOutDevice *dev, std::string name) { - SMidiDev d; - d.dev=dev;d.name=name; - d.refcnt=0; - mididev.push_back(d); + SMidiDev d; + d.dev = dev; + d.name = name; + d.refcnt = 0; + mididev.push_back(d); } void CMidiPlayer::unregisterMidiOutDevice(std::string name) { - for(auto i=mididev.begin();i!=mididev.end();++i) - if(i->name==name) - { - i->dev->deviceDeinit(); - mididev.erase(i); - break; - } + for (auto i = mididev.begin(); i != mididev.end(); ++i) + if (i->name == name) + { + i->dev->deviceDeinit(); + mididev.erase(i); + break; + } } std::vector<std::string> CMidiPlayer::getMidiOutDevices() { - std::vector<std::string> ret; - for(auto &i:mididev) - ret.push_back(i.name); - return ret; + std::vector<std::string> ret; + for (auto &i : mididev) + ret.push_back(i.name); + return ret; } int CMidiPlayer::getChannelOutput(int ch) { - return mappedoutput[ch]; -} -qmpMidiOutDevice* CMidiPlayer::getChannelOutputDevice(int ch) -{ - return mididev[mappedoutput[ch]].dev; -} -void CMidiPlayer::setChannelOutput(int ch,int outid) -{ - int origoutput=mappedoutput[ch]; - if(origoutput==outid) - return; - SMidiDev& dnew=mididev[outid]; - dnew.dev->onMapped(ch,++dnew.refcnt); - for(int i=0;i<124;++i) - { - if(i!=6&&i!=38&&i!=100&&i!=101)//avoid sending RPN/NRPN - { - unsigned st=chstatus[ch][i]; - if(!~st) - st=dnew.dev->getInitialCCValue(i,ch); - dnew.dev->basicMessage(0xB0|ch,i,chstatus[ch][i]); - } - } - dnew.dev->basicMessage(0xC0|ch,~chstatus[ch][128]?chstatus[ch][128]:dnew.dev->getInitialCCValue(128,ch),0); - mappedoutput[ch]=outid; - if(~origoutput) - { - SMidiDev& dold=mididev[origoutput]; - dold.dev->onUnmapped(ch,--dold.refcnt); - } -} -const std::chrono::system_clock::time_point* CMidiPlayer::getLastEventTS() -{return levtt;} -int CMidiPlayer::setEventHandlerCB(ICallBack *cb,void *userdata) -{ - for(int i=0;i<16;++i) - { - if(eventHandlerCB[i]==cb)return i; - if(eventHandlerCB[i]==nullptr) - { - eventHandlerCB[i]=cb;eventHandlerCBuserdata[i]=userdata; - return i; - } - } - return -1; + return mappedoutput[ch]; +} +qmpMidiOutDevice *CMidiPlayer::getChannelOutputDevice(int ch) +{ + return mididev[mappedoutput[ch]].dev; +} +void CMidiPlayer::setChannelOutput(int ch, int outid) +{ + int origoutput = mappedoutput[ch]; + if (origoutput == outid) + return; + SMidiDev &dnew = mididev[outid]; + dnew.dev->onMapped(ch, ++dnew.refcnt); + for (int i = 0; i < 124; ++i) + { + if (i != 6 && i != 38 && i != 100 && i != 101) //avoid sending RPN/NRPN + { + unsigned st = chstatus[ch][i]; + if (!~st) + st = dnew.dev->getInitialCCValue(i, ch); + dnew.dev->basicMessage(0xB0 | ch, i, chstatus[ch][i]); + } + } + dnew.dev->basicMessage(0xC0 | ch, ~chstatus[ch][128] ? chstatus[ch][128] : dnew.dev->getInitialCCValue(128, ch), 0); + mappedoutput[ch] = outid; + if (~origoutput) + { + SMidiDev &dold = mididev[origoutput]; + dold.dev->onUnmapped(ch, --dold.refcnt); + } +} +const std::chrono::system_clock::time_point *CMidiPlayer::getLastEventTS() +{ + return levtt; +} +int CMidiPlayer::setEventHandlerCB(ICallBack *cb, void *userdata) +{ + for (int i = 0; i < 16; ++i) + { + if (eventHandlerCB[i] == cb) + return i; + if (eventHandlerCB[i] == nullptr) + { + eventHandlerCB[i] = cb; + eventHandlerCBuserdata[i] = userdata; + return i; + } + } + return -1; } void CMidiPlayer::unsetEventHandlerCB(int id) -{eventHandlerCB[id]=nullptr;eventHandlerCBuserdata[id]=nullptr;} -int CMidiPlayer::setEventReaderCB(ICallBack *cb,void *userdata) -{ - for(int i=0;i<16;++i) - { - if(eventReaderCB[i]==cb)return i; - if(eventReaderCB[i]==nullptr) - { - eventReaderCB[i]=cb;eventReaderCBuserdata[i]=userdata; - return i; - } - } - return -1; +{ + eventHandlerCB[id] = nullptr; + eventHandlerCBuserdata[id] = nullptr; +} +int CMidiPlayer::setEventReaderCB(ICallBack *cb, void *userdata) +{ + for (int i = 0; i < 16; ++i) + { + if (eventReaderCB[i] == cb) + return i; + if (eventReaderCB[i] == nullptr) + { + eventReaderCB[i] = cb; + eventReaderCBuserdata[i] = userdata; + return i; + } + } + return -1; } void CMidiPlayer::unsetEventReaderCB(int id) -{eventReaderCB[id]=nullptr;eventReaderCBuserdata[id]=nullptr;} -int CMidiPlayer::setFileReadFinishedCB(ICallBack *cb,void *userdata) -{ - for(int i=0;i<16;++i) - { - if(fileReadFinishCB[i]==cb)return i; - if(fileReadFinishCB[i]==nullptr) - { - fileReadFinishCB[i]=cb;fileReadFinishCBuserdata[i]=userdata; - return i; - } - } - return -1; +{ + eventReaderCB[id] = nullptr; + eventReaderCBuserdata[id] = nullptr; +} +int CMidiPlayer::setFileReadFinishedCB(ICallBack *cb, void *userdata) +{ + for (int i = 0; i < 16; ++i) + { + if (fileReadFinishCB[i] == cb) + return i; + if (fileReadFinishCB[i] == nullptr) + { + fileReadFinishCB[i] = cb; + fileReadFinishCBuserdata[i] = userdata; + return i; + } + } + return -1; } void CMidiPlayer::unsetFileReadFinishedCB(int id) -{fileReadFinishCB[id]=nullptr;fileReadFinishCBuserdata[id]=nullptr;} -int CMidiPlayer::registerEventHandler(callback_t cb,void *userdata,bool post) { - int ret; - event_handlers[ret=event_handlers_id++]=std::make_tuple(cb,userdata,post); - return ret; + fileReadFinishCB[id] = nullptr; + fileReadFinishCBuserdata[id] = nullptr; +} +int CMidiPlayer::registerEventHandler(callback_t cb, void *userdata, bool post) +{ + int ret; + event_handlers[ret = event_handlers_id++] = std::make_tuple(cb, userdata, post); + return ret; } void CMidiPlayer::unregisterEventHandler(int id) { - event_handlers.find(id)!=event_handlers.end()&&event_handlers.erase(id); + event_handlers.find(id) != event_handlers.end() &&event_handlers.erase(id); } -int CMidiPlayer::registerEventReadHandler(callback_t cb,void *userdata) +int CMidiPlayer::registerEventReadHandler(callback_t cb, void *userdata) { - int ret; - event_read_handlers[ret=event_read_handlers_id++]=std::make_pair(cb,userdata); - return ret; + int ret; + event_read_handlers[ret = event_read_handlers_id++] = std::make_pair(cb, userdata); + return ret; } void CMidiPlayer::unregisterEventReadHandler(int id) { - event_read_handlers.find(id)!=event_read_handlers.end()&&event_read_handlers.erase(id); + event_read_handlers.find(id) != event_read_handlers.end() &&event_read_handlers.erase(id); } -int CMidiPlayer::registerFileReadFinishHook(callback_t cb,void *userdata) +int CMidiPlayer::registerFileReadFinishHook(callback_t cb, void *userdata) { - int ret; - file_read_finish_hooks[ret=file_read_finish_hooks_id++]=std::make_pair(cb,userdata); - return ret; + int ret; + file_read_finish_hooks[ret = file_read_finish_hooks_id++] = std::make_pair(cb, userdata); + return ret; } void CMidiPlayer::unregisterFileReadFinishHook(int id) { - file_read_finish_hooks.find(id)!=file_read_finish_hooks.end()&&file_read_finish_hooks.erase(id); + file_read_finish_hooks.find(id) != file_read_finish_hooks.end() &&file_read_finish_hooks.erase(id); +} +void CMidiPlayer::registerReader(qmpFileReader *reader, std::string name) +{ + midiReaders->registerReader(reader, name); } -void CMidiPlayer::registerReader(qmpFileReader *reader,std::string name) -{midiReaders->registerReader(reader,name);} void CMidiPlayer::unregisterReader(std::string name) -{midiReaders->unregisterReader(name);} +{ + midiReaders->unregisterReader(name); +} void CMidiPlayer::callEventReaderCB(SEvent d) { - if((d.type&0xF0)==0x90)++notes; - for(int i=0;i<16;++i)if(eventReaderCB[i]) - eventReaderCB[i]->callBack(&d,eventReaderCBuserdata[i]); - for(auto i=event_read_handlers.begin();i!=event_read_handlers.end();++i) - i->second.first(&d,i->second.second); + if ((d.type & 0xF0) == 0x90) + ++notes; + for (int i = 0; i < 16; ++i) + if (eventReaderCB[i]) + eventReaderCB[i]->callBack(&d, eventReaderCBuserdata[i]); + for (auto i = event_read_handlers.begin(); i != event_read_handlers.end(); ++i) + i->second.first(&d, i->second.second); } void CMidiPlayer::discardCurrentEvent() { - if(midiReaders->getCurrentReader()) - midiReaders->getCurrentReader()->discardCurrentEvent(); + if (midiReaders->getCurrentReader()) + midiReaders->getCurrentReader()->discardCurrentEvent(); } void CMidiPlayer::commitEventChange(SEvent d) { - if(midiReaders->getCurrentReader()) - midiReaders->getCurrentReader()->commitEventChange(d); + if (midiReaders->getCurrentReader()) + midiReaders->getCurrentReader()->commitEventChange(d); } -CMidiPlayer* CMidiPlayer::getInstance(){return ref;} +CMidiPlayer *CMidiPlayer::getInstance() +{ + return ref; +} |