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 /qmidiplayer-lite | |
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 'qmidiplayer-lite')
-rw-r--r-- | qmidiplayer-lite/main.cpp | 10 | ||||
-rw-r--r-- | qmidiplayer-lite/qmpcorewrapper.hpp | 106 | ||||
-rw-r--r-- | qmidiplayer-lite/qmpmidiplay.cpp | 749 | ||||
-rw-r--r-- | qmidiplayer-lite/qmpmidiplay.hpp | 237 | ||||
-rw-r--r-- | qmidiplayer-lite/qmpmidiread.cpp | 525 |
5 files changed, 949 insertions, 678 deletions
diff --git a/qmidiplayer-lite/main.cpp b/qmidiplayer-lite/main.cpp index 1a87b33..f0f9af6 100644 --- a/qmidiplayer-lite/main.cpp +++ b/qmidiplayer-lite/main.cpp @@ -5,11 +5,11 @@ int main(int argc, char *argv[]) { - QApplication app(argc, argv); - qmlRegisterType<CQMPCoreWrapper>("org.chrisoft.qmpcore",1,0,"CQMPCoreWrapper"); + QApplication app(argc, argv); + qmlRegisterType<CQMPCoreWrapper>("org.chrisoft.qmpcore", 1, 0, "CQMPCoreWrapper"); - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - return app.exec(); + return app.exec(); } diff --git a/qmidiplayer-lite/qmpcorewrapper.hpp b/qmidiplayer-lite/qmpcorewrapper.hpp index 090edc7..07dff65 100644 --- a/qmidiplayer-lite/qmpcorewrapper.hpp +++ b/qmidiplayer-lite/qmpcorewrapper.hpp @@ -5,56 +5,66 @@ #include <thread> #include <fluidsynth.h> #include "../core/qmpmidiplay.hpp" -class CQMPCoreWrapper:public QObject +class CQMPCoreWrapper: public QObject { - Q_OBJECT + Q_OBJECT private: - CMidiPlayer *mp; - std::thread *playerTh; - int curprog; + CMidiPlayer *mp; + std::thread *playerTh; + int curprog; public: - explicit CQMPCoreWrapper(QObject* parent=0):QObject(parent) - { - mp=new CMidiPlayer(); - } - ~CQMPCoreWrapper(){delete mp;} - Q_INVOKABLE void initFluidSynth(QUrl sfpath) - { - mp->fluid()->setOptStr("audio.driver","pulseaudio"); - mp->fluid()->deviceInit(); - mp->fluid()->loadSFont(sfpath.toLocalFile().toStdString().c_str()); - for(int i=0;i<16;++i) - mp->setChannelOutput(i,0); - } - Q_INVOKABLE void deinitFluidSynth() - { - mp->fluid()->deviceDeinit(); - } - Q_INVOKABLE void loadFile(QUrl file) - { - mp->playerLoadFile(file.toLocalFile().toStdString().c_str()); - mp->playerInit();curprog=0; - } - Q_INVOKABLE void playFile() - { - playerTh=new std::thread(&CMidiPlayer::playerThread,mp); - } - Q_INVOKABLE void stop() - { - mp->playerDeinit();playerTh->join();delete playerTh; - mp->playerPanic(); - } - Q_INVOKABLE int getProgress() - { - while(!mp->isFinished()&&mp->getTCeptr()>mp->getStamp(curprog) - &&curprog<=100) - ++curprog; - return curprog; - } - Q_INVOKABLE void panic(){mp->playerPanic();} - Q_INVOKABLE void setTCeptr(int perct) - { - mp->setTCeptr(mp->getStamp(perct),perct);curprog=perct; - } + explicit CQMPCoreWrapper(QObject *parent = 0): QObject(parent) + { + mp = new CMidiPlayer(); + } + ~CQMPCoreWrapper() + { + delete mp; + } + Q_INVOKABLE void initFluidSynth(QUrl sfpath) + { + mp->fluid()->setOptStr("audio.driver", "pulseaudio"); + mp->fluid()->deviceInit(); + mp->fluid()->loadSFont(sfpath.toLocalFile().toStdString().c_str()); + for (int i = 0; i < 16; ++i) + mp->setChannelOutput(i, 0); + } + Q_INVOKABLE void deinitFluidSynth() + { + mp->fluid()->deviceDeinit(); + } + Q_INVOKABLE void loadFile(QUrl file) + { + mp->playerLoadFile(file.toLocalFile().toStdString().c_str()); + mp->playerInit(); + curprog = 0; + } + Q_INVOKABLE void playFile() + { + playerTh = new std::thread(&CMidiPlayer::playerThread, mp); + } + Q_INVOKABLE void stop() + { + mp->playerDeinit(); + playerTh->join(); + delete playerTh; + mp->playerPanic(); + } + Q_INVOKABLE int getProgress() + { + while (!mp->isFinished() && mp->getTCeptr() > mp->getStamp(curprog) + && curprog <= 100) + ++curprog; + return curprog; + } + Q_INVOKABLE void panic() + { + mp->playerPanic(); + } + Q_INVOKABLE void setTCeptr(int perct) + { + mp->setTCeptr(mp->getStamp(perct), perct); + curprog = perct; + } }; #endif // QMPCOREWRAPPER_H diff --git a/qmidiplayer-lite/qmpmidiplay.cpp b/qmidiplayer-lite/qmpmidiplay.cpp index baec9a2..017de20 100644 --- a/qmidiplayer-lite/qmpmidiplay.cpp +++ b/qmidiplayer-lite/qmpmidiplay.cpp @@ -9,398 +9,531 @@ uint64_t pf; #endif void CMidiPlayer::fluidPreInitialize() { - settings=new_fluid_settings(); + settings = new_fluid_settings(); } void CMidiPlayer::fluidInitialize() { - synth=new_fluid_synth(settings); - adriver=new_fluid_audio_driver(settings,synth); - fluid_synth_set_chorus(synth,FLUID_CHORUS_DEFAULT_N,FLUID_CHORUS_DEFAULT_LEVEL, - FLUID_CHORUS_DEFAULT_SPEED,FLUID_CHORUS_DEFAULT_DEPTH, - FLUID_CHORUS_DEFAULT_TYPE); + synth = new_fluid_synth(settings); + adriver = new_fluid_audio_driver(settings, synth); + fluid_synth_set_chorus(synth, FLUID_CHORUS_DEFAULT_N, FLUID_CHORUS_DEFAULT_LEVEL, + FLUID_CHORUS_DEFAULT_SPEED, FLUID_CHORUS_DEFAULT_DEPTH, + FLUID_CHORUS_DEFAULT_TYPE); #ifndef _WIN32 - if(!singleInstance) - { - if(midiFile->getStandard()==4) - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_MELODIC); - else if(midiFile->getStandard()==1) - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); - else - { - fluid_synth_set_channel_type(synth,9,CHANNEL_TYPE_DRUM); - fluid_synth_bank_select(synth,9,128); - } - } + if (!singleInstance) + { + if (midiFile->getStandard() == 4) + fluid_synth_set_channel_type(synth, 9, CHANNEL_TYPE_MELODIC); + else if (midiFile->getStandard() == 1) + fluid_synth_set_channel_type(synth, 9, CHANNEL_TYPE_DRUM); + else + { + fluid_synth_set_channel_type(synth, 9, CHANNEL_TYPE_DRUM); + fluid_synth_bank_select(synth, 9, 128); + } + } #endif } void CMidiPlayer::fluidDeinitialize() { - if(!synth||!adriver||!settings)return; - delete_fluid_settings(settings); - delete_fluid_audio_driver(adriver); - delete_fluid_synth(synth); - settings=NULL;synth=NULL;adriver=NULL; + if (!synth || !adriver || !settings)return; + delete_fluid_settings(settings); + delete_fluid_audio_driver(adriver); + delete_fluid_synth(synth); + settings = NULL; + synth = NULL; + adriver = NULL; } void CMidiPlayer::processEvent(const SEvent *e) { - switch(e->type&0xF0) - { - case 0x80://Note off - fluid_synth_noteoff(synth,e->type&0x0F,e->p1); - break; - case 0x90://Note on - if((mute>>(e->type&0x0F))&1)break;//muted - if(solo&&!((solo>>(e->type&0x0F))&1))break; - fluid_synth_noteon(synth,e->type&0x0F,e->p1,e->p2); - break; - case 0xB0://CC - if(e->p1==100)rpnid=e->p2; - if(e->p1==6)rpnval=e->p2; - if(~rpnid&&~rpnval) - { - if(rpnid==0)fluid_synth_pitch_wheel_sens(synth,e->type&0x0F,rpnval); - rpnid=rpnval=-1; - } - fluid_synth_cc(synth,e->type&0x0F,e->p1,e->p2); - break; - case 0xC0://PC - fluid_synth_program_change(synth,e->type&0x0F,e->p1); - break; - case 0xE0://PW - fluid_synth_pitch_bend(synth,e->type&0x0F,e->p1); - break; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - ctempo=e->p2;dpt=ctempo*1000/divs; - break; - case 0x58: - ctsn=e->p2>>24; - ctsd=1<<((e->p2>>16)&0xFF); - break; - case 0x59: - cks=e->p2; - 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) - { - int io=0; - if(sendSysEx)fluid_synth_sysex(synth,e->str,e->p1,NULL,&io,NULL,0); - } - break; - } + switch (e->type & 0xF0) + { + case 0x80://Note off + fluid_synth_noteoff(synth, e->type & 0x0F, e->p1); + break; + case 0x90://Note on + if ((mute >> (e->type & 0x0F)) & 1)break; //muted + if (solo && !((solo >> (e->type & 0x0F)) & 1))break; + fluid_synth_noteon(synth, e->type & 0x0F, e->p1, e->p2); + break; + case 0xB0://CC + if (e->p1 == 100)rpnid = e->p2; + if (e->p1 == 6)rpnval = e->p2; + if (~rpnid && ~rpnval) + { + if (rpnid == 0)fluid_synth_pitch_wheel_sens(synth, e->type & 0x0F, rpnval); + rpnid = rpnval = -1; + } + fluid_synth_cc(synth, e->type & 0x0F, e->p1, e->p2); + break; + case 0xC0://PC + fluid_synth_program_change(synth, e->type & 0x0F, e->p1); + break; + case 0xE0://PW + fluid_synth_pitch_bend(synth, e->type & 0x0F, e->p1); + break; + case 0xF0://Meta/SysEx + if ((e->type & 0x0F) == 0x0F) + { + switch (e->p1) + { + case 0x51: + ctempo = e->p2; + dpt = ctempo * 1000 / divs; + break; + case 0x58: + ctsn = e->p2 >> 24; + ctsd = 1 << ((e->p2 >> 16) & 0xFF); + break; + case 0x59: + cks = e->p2; + 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) + { + int io = 0; + if (sendSysEx)fluid_synth_sysex(synth, e->str, e->p1, NULL, &io, NULL, 0); + } + break; + } } void CMidiPlayer::processEventStub(const SEvent *e) { - switch(e->type&0xF0) - { - case 0xB0://CC - if(e->p1==100)rpnid=e->p2; - if(e->p1==6)rpnval=e->p2; - if(~rpnid&&~rpnval) - { - if(rpnid==0)ccc[e->type&0x0F][134]=rpnval; - rpnid=rpnval=-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; - break; - case 0xF0://Meta/SysEx - if((e->type&0x0F)==0x0F) - { - switch(e->p1) - { - case 0x51: - ctempo=e->p2;dpt=ctempo*1000/divs; - ccc[0][131]=dpt; - break; - case 0x58: - ccc[0][132]=e->p2; - break; - case 0x59: - ccc[0][133]=e->p2; - break; - } - } - break; - } + switch (e->type & 0xF0) + { + case 0xB0://CC + if (e->p1 == 100)rpnid = e->p2; + if (e->p1 == 6)rpnval = e->p2; + if (~rpnid && ~rpnval) + { + if (rpnid == 0)ccc[e->type & 0x0F][134] = rpnval; + rpnid = rpnval = -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; + break; + case 0xF0://Meta/SysEx + if ((e->type & 0x0F) == 0x0F) + { + switch (e->p1) + { + case 0x51: + ctempo = e->p2; + dpt = ctempo * 1000 / divs; + ccc[0][131] = dpt; + break; + case 0x58: + ccc[0][132] = e->p2; + break; + case 0x59: + ccc[0][133] = e->p2; + break; + } + } + break; + } } #ifdef _WIN32 void w32usleep(uint64_t t) { - uint64_t st=0,ct=0; - 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); + uint64_t st = 0, ct = 0; + 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); } #endif void CMidiPlayer::playEvents() { - for(uint32_t ct=midiFile->getEvent(0)->time;tceptr<midiFile->getEventCount();) - { - while(tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); - while(!tcstop&&midiFile&&tceptr<midiFile->getEventCount()&&ct==midiFile->getEvent(tceptr)->time) - processEvent(midiFile->getEvent(tceptr++)); - if(tcstop||!midiFile||tceptr>=midiFile->getEventCount())break; - if(resumed)resumed=false; - else + for (uint32_t ct = midiFile->getEvent(0)->time; tceptr < midiFile->getEventCount();) + { + while (tcpaused)std::this_thread::sleep_for(std::chrono::milliseconds(100)); + while (!tcstop && midiFile && tceptr < midiFile->getEventCount() && ct == midiFile->getEvent(tceptr)->time) + processEvent(midiFile->getEvent(tceptr++)); + if (tcstop || !midiFile || tceptr >= midiFile->getEventCount())break; + if (resumed)resumed = false; + else #ifdef _WIN32 - w32usleep((midiFile->getEvent(tceptr)->time-ct)*(dpt/1000)); + w32usleep((midiFile->getEvent(tceptr)->time - ct) * (dpt / 1000)); #else - std::this_thread::sleep_for(std::chrono::nanoseconds(midiFile->getEvent(tceptr)->time-ct)*dpt); + std::this_thread::sleep_for(std::chrono::nanoseconds(midiFile->getEvent(tceptr)->time - ct)*dpt); #endif - if(tcstop||!midiFile)break; - ct=midiFile->getEvent(tceptr)->time; - } - while(!tcstop&&synth&&(waitvoice&&fluid_synth_get_active_voice_count(synth)>0))std::this_thread::sleep_for(std::chrono::milliseconds(2)); - finished=1; + if (tcstop || !midiFile)break; + ct = midiFile->getEvent(tceptr)->time; + } + while (!tcstop && synth && (waitvoice && fluid_synth_get_active_voice_count(synth) > 0))std::this_thread::sleep_for(std::chrono::milliseconds(2)); + finished = 1; } void CMidiPlayer::fileTimer1Pass() { - ftime=.0;ctempo=0x7A120;dpt=ctempo*1000/divs; - for(uint32_t eptr=0,ct=midiFile->getEvent(0)->time;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&ct==midiFile->getEvent(eptr)->time) - processEventStub(midiFile->getEvent(eptr++)); - if(eptr>=midiFile->getEventCount())break; - ftime+=(midiFile->getEvent(eptr)->time-ct)*dpt/1e9; - ct=midiFile->getEvent(eptr)->time; - } + ftime = .0; + ctempo = 0x7A120; + dpt = ctempo * 1000 / divs; + for (uint32_t eptr = 0, ct = midiFile->getEvent(0)->time; eptr < midiFile->getEventCount();) + { + while (eptr < midiFile->getEventCount() && ct == midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if (eptr >= midiFile->getEventCount())break; + ftime += (midiFile->getEvent(eptr)->time - ct) * dpt / 1e9; + ct = midiFile->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));rpnid=rpnval=-1;for(int i=0;i<16;++i) - { - ccc[i][7]=100;ccc[i][10]=64;ccc[i][11]=127; - ccc[i][11]=127;ccc[i][71]=64;ccc[i][72]=64; - ccc[i][73]=64;ccc[i][74]=64;ccc[i][75]=64; - ccc[i][76]=64;ccc[i][77]=64;ccc[i][78]=64; - ccc[0][131]=dpt;ccc[0][132]=0x04021808; - ccc[0][133]=0;ccc[0][134]=2; - }if(midiFile->getStandard()!=4)ccc[9][0]=128; - 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=midiFile->getEvent(0)->time;eptr<midiFile->getEventCount();) - { - while(eptr<midiFile->getEventCount()&&ct==midiFile->getEvent(eptr)->time) - processEventStub(midiFile->getEvent(eptr++)); - if(eptr>=midiFile->getEventCount())break; - ctime+=(midiFile->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=midiFile->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++]=midiFile->getEventCount(); - } + 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)); + rpnid = rpnval = -1; + for (int i = 0; i < 16; ++i) + { + ccc[i][7] = 100; + ccc[i][10] = 64; + ccc[i][11] = 127; + ccc[i][11] = 127; + ccc[i][71] = 64; + ccc[i][72] = 64; + ccc[i][73] = 64; + ccc[i][74] = 64; + ccc[i][75] = 64; + ccc[i][76] = 64; + ccc[i][77] = 64; + ccc[i][78] = 64; + ccc[0][131] = dpt; + ccc[0][132] = 0x04021808; + ccc[0][133] = 0; + ccc[0][134] = 2; + } + if (midiFile->getStandard() != 4)ccc[9][0] = 128; + 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 = midiFile->getEvent(0)->time; eptr < midiFile->getEventCount();) + { + while (eptr < midiFile->getEventCount() && ct == midiFile->getEvent(eptr)->time) + processEventStub(midiFile->getEvent(eptr++)); + if (eptr >= midiFile->getEventCount())break; + ctime += (midiFile->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 = midiFile->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++] = midiFile->getEventCount(); + } } CMidiPlayer::CMidiPlayer(bool singleInst) { - midiFile=NULL;resumed=false;singleInstance=singleInst; - settings=NULL;synth=NULL;adriver=NULL;waitvoice=true; + midiFile = NULL; + resumed = false; + singleInstance = singleInst; + settings = NULL; + synth = NULL; + adriver = NULL; + waitvoice = true; #ifdef _WIN32 - QueryPerformanceFrequency((LARGE_INTEGER*)&pf); - timeBeginPeriod(1); + QueryPerformanceFrequency((LARGE_INTEGER *)&pf); + timeBeginPeriod(1); #endif } CMidiPlayer::~CMidiPlayer() { - if(singleInstance)fluidDeinitialize(); + if (singleInstance)fluidDeinitialize(); #ifdef _WIN32 - timeEndPeriod(1); + timeEndPeriod(1); #endif } void CMidiPlayer::playerPanic(bool reset) { - if(reset)for(int i=0;i<16;++i) - { - fluid_synth_pitch_bend(synth,i,8192); - fluid_synth_cc(synth,i,7,100); - fluid_synth_cc(synth,i,10,64); - fluid_synth_cc(synth,i,11,127); - } - for(int i=0;i<16;++i)fluid_synth_all_notes_off(synth,i); + if (reset)for (int i = 0; i < 16; ++i) + { + fluid_synth_pitch_bend(synth, i, 8192); + fluid_synth_cc(synth, i, 7, 100); + fluid_synth_cc(synth, i, 10, 64); + fluid_synth_cc(synth, i, 11, 127); + } + for (int i = 0; i < 16; ++i)fluid_synth_all_notes_off(synth, i); } -bool CMidiPlayer::playerLoadFile(const char* fn) +bool CMidiPlayer::playerLoadFile(const char *fn) { - midiFile=new CMidiFile(fn); - if(!midiFile->isValid())return false; - divs=midiFile->getDivision(); - fileTimer1Pass(); - fileTimer2Pass(); - return true; + midiFile = new CMidiFile(fn); + if (!midiFile->isValid())return false; + divs = midiFile->getDivision(); + fileTimer1Pass(); + fileTimer2Pass(); + return true; } void CMidiPlayer::playerInit() { - ctempo=0x7A120;ctsn=4;ctsd=4;cks=0;dpt=ctempo*1000/divs; - tceptr=0;tcstop=0;tcpaused=0;finished=0;mute=solo=0; - sendSysEx=true;rpnid=rpnval=-1; - if(!singleInstance)fluidPreInitialize(); + ctempo = 0x7A120; + ctsn = 4; + ctsd = 4; + cks = 0; + dpt = ctempo * 1000 / divs; + tceptr = 0; + tcstop = 0; + tcpaused = 0; + finished = 0; + mute = solo = 0; + sendSysEx = true; + rpnid = rpnval = -1; + if (!singleInstance)fluidPreInitialize(); } void CMidiPlayer::playerDeinit() { - tceptr=0;tcstop=1;tcpaused=0; - delete midiFile;midiFile=NULL; - if(!singleInstance)fluidDeinitialize(); + tceptr = 0; + tcstop = 1; + tcpaused = 0; + delete midiFile; + midiFile = NULL; + if (!singleInstance)fluidDeinitialize(); } void CMidiPlayer::playerThread() { - playEvents(); + playEvents(); } -void CMidiPlayer::rendererLoadFile(const char* ofn) +void CMidiPlayer::rendererLoadFile(const char *ofn) { - settings=new_fluid_settings(); - fluid_settings_setstr(settings,"audio.file.name",ofn); + settings = new_fluid_settings(); + fluid_settings_setstr(settings, "audio.file.name", ofn); } -void CMidiPlayer::rendererInit(const char* fn) +void CMidiPlayer::rendererInit(const char *fn) { - finished=0; - synth=new_fluid_synth(settings); - player=new_fluid_player(synth); - fluid_player_add(player,fn); + finished = 0; + synth = new_fluid_synth(settings); + player = new_fluid_player(synth); + fluid_player_add(player, fn); } void CMidiPlayer::rendererThread() { - fluid_file_renderer_t* renderer=new_fluid_file_renderer(synth); - fluid_player_play(player); - while(fluid_player_get_status(player)==FLUID_PLAYER_PLAYING) - if(fluid_file_renderer_process_block(renderer)!=FLUID_OK)break; - delete_fluid_file_renderer(renderer); - finished=1; + fluid_file_renderer_t *renderer = new_fluid_file_renderer(synth); + fluid_player_play(player); + while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) + if (fluid_file_renderer_process_block(renderer) != FLUID_OK)break; + delete_fluid_file_renderer(renderer); + finished = 1; } void CMidiPlayer::rendererDeinit() { - delete_fluid_player(player); - delete_fluid_synth(synth); - delete_fluid_settings(settings); - player=NULL;synth=NULL;settings=NULL; + delete_fluid_player(player); + delete_fluid_synth(synth); + delete_fluid_settings(settings); + player = NULL; + synth = NULL; + settings = NULL; } -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==midiFile->getEventCount())tcstop=1;else tceptr=ep; - for(int i=0;i<16;++i) - { - for(int j=0;j<120;++j)fluid_synth_cc(synth,i,j,ccstamps[st][i][j]); - fluid_synth_program_change(synth,i,ccstamps[st][i][128]); - //fluid_synth_pitch_bend(synth,i,ccstamps[st][i][130]); - dpt=ccstamps[st][0][131];ctempo=dpt*divs/1000; - 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;} -void CMidiPlayer::getCurrentKeySignature(int *ks){*ks=cks;} -uint32_t CMidiPlayer::getFileNoteCount(){return midiFile?midiFile->getNoteCount():0;} -uint32_t CMidiPlayer::getFileStandard(){return midiFile?midiFile->getStandard():0;} -const char* CMidiPlayer::getTitle(){return midiFile?midiFile->getTitle():"";} -const char* CMidiPlayer::getCopyright(){return midiFile?midiFile->getCopyright():"";} -double CMidiPlayer::getTempo(){return 60./(ctempo/1e6)/**ctsd/4.*/;} -uint32_t CMidiPlayer::getTCpaused(){return tcpaused;} -void CMidiPlayer::setTCpaused(uint32_t ps){tcpaused=ps;} -uint32_t CMidiPlayer::isFinished(){return finished;} -void CMidiPlayer::setResumed(){resumed=true;} -void CMidiPlayer::setWaitVoice(bool wv){waitvoice=wv;} -void CMidiPlayer::setGain(double gain){if(settings)fluid_settings_setnum(settings,"synth.gain",gain);} -int CMidiPlayer::getPolyphone(){return synth?fluid_synth_get_active_voice_count(synth):0;} -int CMidiPlayer::getMaxPolyphone(){return synth?fluid_synth_get_polyphony(synth):0;} -void CMidiPlayer::setMaxPolyphone(int p){if(synth)fluid_synth_set_polyphony(synth,p);} +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 == midiFile->getEventCount())tcstop = 1; + else tceptr = ep; + for (int i = 0; i < 16; ++i) + { + for (int j = 0; j < 120; ++j)fluid_synth_cc(synth, i, j, ccstamps[st][i][j]); + fluid_synth_program_change(synth, i, ccstamps[st][i][128]); + //fluid_synth_pitch_bend(synth,i,ccstamps[st][i][130]); + dpt = ccstamps[st][0][131]; + ctempo = dpt * divs / 1000; + 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; +} +void CMidiPlayer::getCurrentKeySignature(int *ks) +{ + *ks = cks; +} +uint32_t CMidiPlayer::getFileNoteCount() +{ + return midiFile ? midiFile->getNoteCount() : 0; +} +uint32_t CMidiPlayer::getFileStandard() +{ + return midiFile ? midiFile->getStandard() : 0; +} +const char *CMidiPlayer::getTitle() +{ + return midiFile ? midiFile->getTitle() : ""; +} +const char *CMidiPlayer::getCopyright() +{ + return midiFile ? midiFile->getCopyright() : ""; +} +double CMidiPlayer::getTempo() +{ + return 60. / (ctempo / 1e6)/**ctsd/4.*/; +} +uint32_t CMidiPlayer::getTCpaused() +{ + return tcpaused; +} +void CMidiPlayer::setTCpaused(uint32_t ps) +{ + tcpaused = ps; +} +uint32_t CMidiPlayer::isFinished() +{ + return finished; +} +void CMidiPlayer::setResumed() +{ + resumed = true; +} +void CMidiPlayer::setWaitVoice(bool wv) +{ + waitvoice = wv; +} +void CMidiPlayer::setGain(double gain) +{ + if (settings)fluid_settings_setnum(settings, "synth.gain", gain); +} +int CMidiPlayer::getPolyphone() +{ + return synth ? fluid_synth_get_active_voice_count(synth) : 0; +} +int CMidiPlayer::getMaxPolyphone() +{ + return synth ? fluid_synth_get_polyphony(synth) : 0; +} +void CMidiPlayer::setMaxPolyphone(int p) +{ + if (synth)fluid_synth_set_polyphony(synth, p); +} -void CMidiPlayer::getChannelPreset(int ch,int *b,int *p,char *name) +void CMidiPlayer::getChannelPreset(int ch, int *b, int *p, char *name) { - if(!synth)return(void)(b=0,p=0,strcpy(name,"")); - fluid_synth_channel_info_t info; - fluid_synth_get_channel_info(synth,ch,&info); - *b=info.bank;*p=info.program; - strcpy(name,info.name); + if (!synth)return (void)(b = 0, p = 0, strcpy(name, "")); + fluid_synth_channel_info_t info; + fluid_synth_get_channel_info(synth, ch, &info); + *b = info.bank; + *p = info.program; + strcpy(name, info.name); } -void CMidiPlayer::setChannelPreset(int ch,int b,int p) +void CMidiPlayer::setChannelPreset(int ch, int b, int p) { - if(!synth)return; - fluid_synth_bank_select(synth,ch,b); - fluid_synth_program_change(synth,ch,p); + if (!synth)return; + fluid_synth_bank_select(synth, ch, b); + fluid_synth_program_change(synth, ch, p); } //16MSB..LSB1 void CMidiPlayer::setBit(uint16_t &n, uint16_t bn, uint16_t b) -{n^=(-b^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 ^ 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); +} int CMidiPlayer::getCC(int ch, int id) -{int ret=0;synth?fluid_synth_get_cc(synth,ch,id,&ret):0;return ret;} +{ + int ret = 0; + synth ? fluid_synth_get_cc(synth, ch, id, &ret) : 0; + return ret; +} void CMidiPlayer::setCC(int ch, int id, int val) -{synth?fluid_synth_cc(synth,ch,id,val):0;} -void CMidiPlayer::getReverbPara(double *r,double *d,double *w,double *l) { - if(!synth)return; - *r=fluid_synth_get_reverb_roomsize(synth); - *d=fluid_synth_get_reverb_damp(synth); - *w=fluid_synth_get_reverb_width(synth); - *l=fluid_synth_get_reverb_level(synth); + synth ? fluid_synth_cc(synth, ch, id, val) : 0; +} +void CMidiPlayer::getReverbPara(double *r, double *d, double *w, double *l) +{ + if (!synth)return; + *r = fluid_synth_get_reverb_roomsize(synth); + *d = fluid_synth_get_reverb_damp(synth); + *w = fluid_synth_get_reverb_width(synth); + *l = fluid_synth_get_reverb_level(synth); } -void CMidiPlayer::setReverbPara(int e,double r,double d,double w,double l) +void CMidiPlayer::setReverbPara(int e, double r, double d, double w, double l) { - if(!synth)return; - fluid_synth_set_reverb_on(synth,e); - fluid_synth_set_reverb(synth,r,d,w,l); + if (!synth)return; + fluid_synth_set_reverb_on(synth, e); + fluid_synth_set_reverb(synth, r, d, w, l); } -void CMidiPlayer::getChorusPara(int *fb,double *l,double *r,double *d,int *type) +void CMidiPlayer::getChorusPara(int *fb, double *l, double *r, double *d, int *type) { - if(!synth)return; - *fb=fluid_synth_get_chorus_nr(synth); - *l=fluid_synth_get_chorus_level(synth); - *r=fluid_synth_get_chorus_speed_Hz(synth); - *d=fluid_synth_get_chorus_depth_ms(synth); - *type=fluid_synth_get_chorus_type(synth); + if (!synth)return; + *fb = fluid_synth_get_chorus_nr(synth); + *l = fluid_synth_get_chorus_level(synth); + *r = fluid_synth_get_chorus_speed_Hz(synth); + *d = fluid_synth_get_chorus_depth_ms(synth); + *type = fluid_synth_get_chorus_type(synth); } -void CMidiPlayer::setChorusPara(int e,int fb,double l,double r,double d,int type) +void CMidiPlayer::setChorusPara(int e, int fb, double l, double r, double d, int type) { - if(!synth)return; - fluid_synth_set_chorus_on(synth,e); - fluid_synth_set_chorus(synth,fb,l,r,d,type); + if (!synth)return; + fluid_synth_set_chorus_on(synth, e); + fluid_synth_set_chorus(synth, fb, l, r, d, type); +} +fluid_settings_t *CMidiPlayer::getFluidSettings() +{ + return settings; } -fluid_settings_t* CMidiPlayer::getFluidSettings(){return settings;} void CMidiPlayer::pushSoundFont(const char *sf) -{fluid_synth_sfload(synth,sf,1);} +{ + fluid_synth_sfload(synth, sf, 1); +} int CMidiPlayer::getSFCount() -{return synth?fluid_synth_sfcount(synth):0;} -fluid_sfont_t* CMidiPlayer::getSFPtr(int sfid) -{return synth&&sfid<getSFCount()?fluid_synth_get_sfont(synth,sfid):NULL;} +{ + return synth ? fluid_synth_sfcount(synth) : 0; +} +fluid_sfont_t *CMidiPlayer::getSFPtr(int sfid) +{ + return synth && sfid < getSFCount() ? fluid_synth_get_sfont(synth, sfid) : NULL; +} diff --git a/qmidiplayer-lite/qmpmidiplay.hpp b/qmidiplayer-lite/qmpmidiplay.hpp index fafd677..e2ef047 100644 --- a/qmidiplayer-lite/qmpmidiplay.hpp +++ b/qmidiplayer-lite/qmpmidiplay.hpp @@ -7,131 +7,144 @@ #include <fluidsynth.h> struct SEvent { - uint32_t iid,time,p1,p2; - uint8_t type; - char *str; - SEvent(){time=p1=p2=0;type=0;str=NULL;} - SEvent(uint32_t _iid,uint32_t _t,char _tp,uint32_t _p1,uint32_t _p2,const char* s=NULL) - { - iid=_iid;time=_t;type=_tp; - p1=_p1;p2=_p2; - if(s){str=new char[strlen(s)+2];strcpy(str,s);}else str=NULL; - } + uint32_t iid, time, p1, p2; + uint8_t type; + char *str; + SEvent() + { + time = p1 = p2 = 0; + type = 0; + str = NULL; + } + SEvent(uint32_t _iid, uint32_t _t, char _tp, uint32_t _p1, uint32_t _p2, const char *s = NULL) + { + iid = _iid; + time = _t; + type = _tp; + p1 = _p1; + p2 = _p2; + if (s) + { + str = new char[strlen(s) + 2]; + strcpy(str, s); + } + else str = NULL; + } }; class CMidiFile { - private: - SEvent *eventList[10000000]; - char *title,*copyright; - uint32_t eventc,std;//standard 0=? 1=GM 2=GM2 3=GS 4=XG - uint32_t fmt,trk,divs; - FILE *f; - int byteread,valid; - uint32_t notes,curt,curid; +private: + SEvent *eventList[10000000]; + char *title, *copyright; + uint32_t eventc, std; //standard 0=? 1=GM 2=GM2 3=GS 4=XG + uint32_t fmt, trk, divs; + FILE *f; + int byteread, valid; + uint32_t notes, curt, curid; - void error(int fatal,const char* format,...); - uint32_t readSW(); - uint32_t readDW(); - uint32_t readVL(); - int eventReader(); - void trackChunkReader(); - void headerChunkReader(); - int chunkReader(int hdrXp); - public: - CMidiFile(const char* fn); - ~CMidiFile(); - const SEvent* getEvent(uint32_t id); - uint32_t getEventCount(); - uint32_t getDivision(); - uint32_t getNoteCount(); - uint32_t getStandard(); - const char* getTitle(); - const char* getCopyright(); - bool isValid(); + void error(int fatal, const char *format, ...); + uint32_t readSW(); + uint32_t readDW(); + uint32_t readVL(); + int eventReader(); + void trackChunkReader(); + void headerChunkReader(); + int chunkReader(int hdrXp); +public: + CMidiFile(const char *fn); + ~CMidiFile(); + const SEvent *getEvent(uint32_t id); + uint32_t getEventCount(); + uint32_t getDivision(); + uint32_t getNoteCount(); + uint32_t getStandard(); + const char *getTitle(); + const char *getCopyright(); + bool isValid(); }; class CMidiPlayer { - private: - CMidiFile *midiFile; - uint32_t stamps[101]; - uint32_t ccstamps[101][16][135],ccc[16][135]; - //0..127:cc 128:pc 129:cp 130:pb 131:tempo 132:ts 133:ks 134:pbr - int32_t rpnid,rpnval; - uint16_t mute,solo; - double ftime; - bool sendSysEx,singleInstance,waitvoice; - fluid_settings_t* settings; - fluid_synth_t* synth; - fluid_audio_driver_t* adriver; - fluid_player_t* player; - uint32_t ctempo,ctsn,ctsd,dpt,divs,cks; - //raw tempo, timesig num., timesig den., delay per tick, division, keysig - //thread control - uint32_t tceptr,tcpaused,tcstop; - uint32_t finished,resumed; +private: + CMidiFile *midiFile; + uint32_t stamps[101]; + uint32_t ccstamps[101][16][135], ccc[16][135]; + //0..127:cc 128:pc 129:cp 130:pb 131:tempo 132:ts 133:ks 134:pbr + int32_t rpnid, rpnval; + uint16_t mute, solo; + double ftime; + bool sendSysEx, singleInstance, waitvoice; + fluid_settings_t *settings; + fluid_synth_t *synth; + fluid_audio_driver_t *adriver; + fluid_player_t *player; + uint32_t ctempo, ctsn, ctsd, dpt, divs, cks; + //raw tempo, timesig num., timesig den., delay per tick, division, keysig + //thread control + uint32_t tceptr, tcpaused, tcstop; + uint32_t finished, resumed; - void setBit(uint16_t &n,uint16_t bn,uint16_t b); - void processEvent(const SEvent *e); - void processEventStub(const SEvent *e); - void playEvents(); - void fileTimer1Pass(); - void fileTimer2Pass(); - public: - CMidiPlayer(bool singleInst=false); - ~CMidiPlayer(); - bool playerLoadFile(const char* fn); - void playerInit(); - void fluidPreInitialize(); - void fluidInitialize(); - void fluidDeinitialize(); - void playerDeinit(); - void playerThread(); - void playerPanic(bool reset=false); + void setBit(uint16_t &n, uint16_t bn, uint16_t b); + void processEvent(const SEvent *e); + void processEventStub(const SEvent *e); + void playEvents(); + void fileTimer1Pass(); + void fileTimer2Pass(); +public: + CMidiPlayer(bool singleInst = false); + ~CMidiPlayer(); + bool playerLoadFile(const char *fn); + void playerInit(); + void fluidPreInitialize(); + void fluidInitialize(); + void fluidDeinitialize(); + void playerDeinit(); + void playerThread(); + void playerPanic(bool reset = false); - void rendererLoadFile(const char* ofn); - void rendererInit(const char *fn); - void rendererThread(); - void rendererDeinit(); + void rendererLoadFile(const char *ofn); + void rendererInit(const char *fn); + void rendererThread(); + void rendererDeinit(); - //playing control methods - uint32_t getStamp(int id); - uint32_t getTCeptr(); - void setTCeptr(uint32_t ep,uint32_t st); - uint32_t getTCpaused(); - void setTCpaused(uint32_t ps); - uint32_t isFinished(); - void setResumed(); - void setWaitVoice(bool wv); + //playing control methods + uint32_t getStamp(int id); + uint32_t getTCeptr(); + void setTCeptr(uint32_t ep, uint32_t st); + uint32_t getTCpaused(); + void setTCpaused(uint32_t ps); + uint32_t isFinished(); + void setResumed(); + void setWaitVoice(bool wv); - double getFtime(); - void getCurrentTimeSignature(int *n,int *d); - void getCurrentKeySignature(int *ks); - uint32_t getFileNoteCount(); - uint32_t getFileStandard(); - double getTempo(); - const char* getTitle(); - const char* getCopyright(); + double getFtime(); + void getCurrentTimeSignature(int *n, int *d); + void getCurrentKeySignature(int *ks); + uint32_t getFileNoteCount(); + uint32_t getFileStandard(); + double getTempo(); + const char *getTitle(); + const char *getCopyright(); - void setGain(double gain); - void sendSysX(bool send); - int getPolyphone(); - int getMaxPolyphone(); - void setMaxPolyphone(int p); + void setGain(double gain); + void sendSysX(bool send); + int getPolyphone(); + int getMaxPolyphone(); + void setMaxPolyphone(int p); - void setChannelPreset(int ch,int b,int p); - void getChannelPreset(int ch,int *b,int *p,char *name); - void setMute(int ch,bool m); - void setSolo(int ch,bool s); - int getCC(int ch,int id); - void setCC(int ch,int id,int val); - void getReverbPara(double *r,double *d,double *w,double *l); - void setReverbPara(int e,double r,double d,double w,double l); - void getChorusPara(int *fb,double *l,double *r,double *d,int *type); - void setChorusPara(int e,int fb,double l,double r,double d,int type); + void setChannelPreset(int ch, int b, int p); + void getChannelPreset(int ch, int *b, int *p, char *name); + void setMute(int ch, bool m); + void setSolo(int ch, bool s); + int getCC(int ch, int id); + void setCC(int ch, int id, int val); + void getReverbPara(double *r, double *d, double *w, double *l); + void setReverbPara(int e, double r, double d, double w, double l); + void getChorusPara(int *fb, double *l, double *r, double *d, int *type); + void setChorusPara(int e, int fb, double l, double r, double d, int type); - fluid_settings_t* getFluidSettings(); - void pushSoundFont(const char* sf); - int getSFCount(); - fluid_sfont_t* getSFPtr(int sfid); + fluid_settings_t *getFluidSettings(); + void pushSoundFont(const char *sf); + int getSFCount(); + fluid_sfont_t *getSFPtr(int sfid); }; #endif diff --git a/qmidiplayer-lite/qmpmidiread.cpp b/qmidiplayer-lite/qmpmidiread.cpp index 0bcf597..227aa7d 100644 --- a/qmidiplayer-lite/qmpmidiread.cpp +++ b/qmidiplayer-lite/qmpmidiread.cpp @@ -8,233 +8,348 @@ #include <cstdarg> #include <algorithm> #include "qmpmidiplay.hpp" -const char* GM1SysX={"\xF0\x7E\x7F\x09\x01\xF7"}; -const char* GM2SysX={"\xF0\x7E\x7F\x09\x03\xF7"}; -const char* GSSysEx={"\xF0\x41\x10\x42\x12\x40\x00\x7F\x00\x41\xF7"}; -const char* XGSysEx={"\xF0\x43\x10\x4C\x00\x00\x7E\x00\xF7"}; -bool cmp(SEvent *a,SEvent *b){return a->time-b->time?a->time<b->time:a->iid<b->iid;} -void CMidiFile::error(int fatal,const char* format,...) -{ - va_list ap; - va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); - fprintf(stderr," at %#lx\n",ftell(f)); - if(fatal)throw 2; +const char *GM1SysX = {"\xF0\x7E\x7F\x09\x01\xF7"}; +const char *GM2SysX = {"\xF0\x7E\x7F\x09\x03\xF7"}; +const char *GSSysEx = {"\xF0\x41\x10\x42\x12\x40\x00\x7F\x00\x41\xF7"}; +const char *XGSysEx = {"\xF0\x43\x10\x4C\x00\x00\x7E\x00\xF7"}; +bool cmp(SEvent *a, SEvent *b) +{ + return a->time - b->time ? a->time < b->time : a->iid < b->iid; +} +void CMidiFile::error(int fatal, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fprintf(stderr, " at %#lx\n", ftell(f)); + if (fatal)throw 2; } uint32_t CMidiFile::readSW() { - byteread+=2; - uint32_t ret=0; - for(int i=0;i<2;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} - return ret; + byteread += 2; + uint32_t ret = 0; + for (int i = 0; i < 2; ++i) + { + ret <<= 8; + ret |= ((uint32_t)fgetc(f)) & 0xFF; + } + return ret; } uint32_t CMidiFile::readDW() { - byteread+=4; - uint32_t ret=0; - for(int i=0;i<4;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} - return ret; + byteread += 4; + uint32_t ret = 0; + for (int i = 0; i < 4; ++i) + { + ret <<= 8; + ret |= ((uint32_t)fgetc(f)) & 0xFF; + } + return ret; } uint32_t CMidiFile::readVL() { - uint32_t ret=0,t,c=0; - do - { - t=fgetc(f); - if(++c>4)error(1,"E: Variable length type overflow."); - ret<<=7;ret|=(t&0x7F); - }while(t&0x80); - byteread+=c; - return ret; + uint32_t ret = 0, t, c = 0; + do + { + t = fgetc(f); + if (++c > 4)error(1, "E: Variable length type overflow."); + ret <<= 7; + ret |= (t & 0x7F); + } while (t & 0x80); + byteread += c; + return ret; } int CMidiFile::eventReader()//returns 0 if End of Track encountered { - uint32_t delta=readVL();curt+=delta; - char type=fgetc(f);++byteread;uint32_t p1,p2; - static char lasttype; + uint32_t delta = readVL(); + curt += delta; + char type = fgetc(f); + ++byteread; + uint32_t p1, p2; + static char lasttype; retry: - switch(type&0xF0) - { - case 0x80://Note Off - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0x90://Note On - p1=fgetc(f);p2=fgetc(f);byteread+=2; - if(p2) - { - ++notes; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - } - else - eventList[eventc++]=new SEvent(curid,curt,(type&0x0F)|0x80,p1,p2); - break; - case 0xA0://Note Aftertouch - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0xB0://Controller Change - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,p1,p2); - break; - case 0xC0://Patch Change - p1=fgetc(f);++byteread; - eventList[eventc++]=new SEvent(curid,curt,type,p1,0); - break; - case 0xD0://Channel Aftertouch - p1=fgetc(f);++byteread; - eventList[eventc++]=new SEvent(curid,curt,type,p1,0); - break; - case 0xE0://Pitch wheel - p1=fgetc(f);p2=fgetc(f);byteread+=2; - eventList[eventc++]=new SEvent(curid,curt,type,(p1|(p2<<7))&0x3FFF,0); - break; - case 0xF0: - if((type&0x0F)==0x0F)//Meta Event - { - char metatype=fgetc(f);++byteread; - switch(metatype) - { - case 0x00://Sequence Number - fgetc(f);fgetc(f);fgetc(f); - byteread+=3; - break; - case 0x20://Channel Prefix - fgetc(f);fgetc(f);byteread+=2; - break; - case 0x2F://End of Track - fgetc(f);++byteread; - return 0; - break; - case 0x51://Set Tempo - p1=readDW();p1&=0x00FFFFFF; - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x54://SMTPE offset, not handled. - fgetc(f);fgetc(f);fgetc(f); - fgetc(f);fgetc(f);fgetc(f); - byteread+=6; - break; - case 0x58://Time signature - fgetc(f);++byteread; - p1=readDW(); - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x59://Key signature - fgetc(f);++byteread; - p1=readSW(); - eventList[eventc++]=new SEvent(curid,curt,type,metatype,p1); - break; - case 0x01:case 0x02:case 0x03: - case 0x04:case 0x05:case 0x06: - case 0x07:case 0x7F:default://text-like meta - { - uint32_t len=readVL(),c;char* str=NULL; - if(len<=1024&&len>0)str=new char[len+8]; - for(c=0;c<len;++c) - { - ++byteread;if(str)str[c]=fgetc(f);else fgetc(f); - } - if(str)str[c]='\0';eventList[eventc++]=new SEvent(curid,curt,type,metatype,0,str); - if(str&&metatype==0x03&&!title) - { - title=new char[len+8]; - strcpy(title,str); - } - if(str&&metatype==0x02&&!copyright) - { - copyright=new char[len+8]; - strcpy(copyright,str); - } - if(len<=1024&&len>0)delete[] str; - } - } - } - else if((type&0x0F)==0x00||(type&0x0F)==0x07)//SysEx - { - uint32_t len=readVL(),c;char* str=NULL; - str=new char[len+8]; - if((type&0x0F)==0x00) - { - str[0]=0xF0;++len; - for(c=1;c<len;++c){++byteread;str[c]=fgetc(f);} - } - else for(c=0;c<len;++c){++byteread;str[c]=fgetc(f);} - eventList[eventc++]=new SEvent(curid,curt,type,len,0,str); - if(!strcmp(str,GM1SysX))std=1; - if(!strcmp(str,GM2SysX))std=2; - if(!strcmp(str,GSSysEx))std=3; - if(!strcmp(str,XGSysEx))std=4; - } - else error(0,"W: Unknown event type %#x",type); - break; - default: - fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;goto retry; - } - lasttype=type;++curid; - return 1; + switch (type & 0xF0) + { + case 0x80://Note Off + p1 = fgetc(f); + p2 = fgetc(f); + byteread += 2; + eventList[eventc++] = new SEvent(curid, curt, type, p1, p2); + break; + case 0x90://Note On + p1 = fgetc(f); + p2 = fgetc(f); + byteread += 2; + if (p2) + { + ++notes; + eventList[eventc++] = new SEvent(curid, curt, type, p1, p2); + } + else + eventList[eventc++] = new SEvent(curid, curt, (type & 0x0F) | 0x80, p1, p2); + break; + case 0xA0://Note Aftertouch + p1 = fgetc(f); + p2 = fgetc(f); + byteread += 2; + eventList[eventc++] = new SEvent(curid, curt, type, p1, p2); + break; + case 0xB0://Controller Change + p1 = fgetc(f); + p2 = fgetc(f); + byteread += 2; + eventList[eventc++] = new SEvent(curid, curt, type, p1, p2); + break; + case 0xC0://Patch Change + p1 = fgetc(f); + ++byteread; + eventList[eventc++] = new SEvent(curid, curt, type, p1, 0); + break; + case 0xD0://Channel Aftertouch + p1 = fgetc(f); + ++byteread; + eventList[eventc++] = new SEvent(curid, curt, type, p1, 0); + break; + case 0xE0://Pitch wheel + p1 = fgetc(f); + p2 = fgetc(f); + byteread += 2; + eventList[eventc++] = new SEvent(curid, curt, type, (p1 | (p2 << 7)) & 0x3FFF, 0); + break; + case 0xF0: + if ((type & 0x0F) == 0x0F) //Meta Event + { + char metatype = fgetc(f); + ++byteread; + switch (metatype) + { + case 0x00://Sequence Number + fgetc(f); + fgetc(f); + fgetc(f); + byteread += 3; + break; + case 0x20://Channel Prefix + fgetc(f); + fgetc(f); + byteread += 2; + break; + case 0x2F://End of Track + fgetc(f); + ++byteread; + return 0; + break; + case 0x51://Set Tempo + p1 = readDW(); + p1 &= 0x00FFFFFF; + eventList[eventc++] = new SEvent(curid, curt, type, metatype, p1); + break; + case 0x54://SMTPE offset, not handled. + fgetc(f); + fgetc(f); + fgetc(f); + fgetc(f); + fgetc(f); + fgetc(f); + byteread += 6; + break; + case 0x58://Time signature + fgetc(f); + ++byteread; + p1 = readDW(); + eventList[eventc++] = new SEvent(curid, curt, type, metatype, p1); + break; + case 0x59://Key signature + fgetc(f); + ++byteread; + p1 = readSW(); + eventList[eventc++] = new SEvent(curid, curt, type, metatype, p1); + break; + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x7F: + default://text-like meta + { + uint32_t len = readVL(), c; + char *str = NULL; + if (len <= 1024 && len > 0)str = new char[len + 8]; + for (c = 0; c < len; ++c) + { + ++byteread; + if (str)str[c] = fgetc(f); + else fgetc(f); + } + if (str)str[c] = '\0'; + eventList[eventc++] = new SEvent(curid, curt, type, metatype, 0, str); + if (str && metatype == 0x03 && !title) + { + title = new char[len + 8]; + strcpy(title, str); + } + if (str && metatype == 0x02 && !copyright) + { + copyright = new char[len + 8]; + strcpy(copyright, str); + } + if (len <= 1024 && len > 0)delete[] str; + } + } + } + else if ((type & 0x0F) == 0x00 || (type & 0x0F) == 0x07) //SysEx + { + uint32_t len = readVL(), c; + char *str = NULL; + str = new char[len + 8]; + if ((type & 0x0F) == 0x00) + { + str[0] = 0xF0; + ++len; + for (c = 1; c < len; ++c) + { + ++byteread; + str[c] = fgetc(f); + } + } + else for (c = 0; c < len; ++c) + { + ++byteread; + str[c] = fgetc(f); + } + eventList[eventc++] = new SEvent(curid, curt, type, len, 0, str); + if (!strcmp(str, GM1SysX))std = 1; + if (!strcmp(str, GM2SysX))std = 2; + if (!strcmp(str, GSSysEx))std = 3; + if (!strcmp(str, XGSysEx))std = 4; + } + else error(0, "W: Unknown event type %#x", type); + break; + default: + fseek(f, -1, SEEK_CUR); + --byteread; + type = lasttype; + goto retry; + } + lasttype = type; + ++curid; + return 1; } void CMidiFile::trackChunkReader() { - int chnklen=readDW();byteread=0;curt=0;curid=0; - while(/*byteread<chnklen&&*/eventReader()); - if(byteread<chnklen) - { - error(0,"W: Extra bytes after EOT event."); - while(byteread<chnklen){fgetc(f);++byteread;} - } - /*if(byteread>chnklen) - { - error(1,"E: Read past end of track."); - }*/ + int chnklen = readDW(); + byteread = 0; + curt = 0; + curid = 0; + while (/*byteread<chnklen&&*/eventReader()); + if (byteread < chnklen) + { + error(0, "W: Extra bytes after EOT event."); + while (byteread < chnklen) + { + fgetc(f); + ++byteread; + } + } + /*if(byteread>chnklen) + { + error(1,"E: Read past end of track."); + }*/ } void CMidiFile::headerChunkReader() { - int chnklen=readDW();byteread=0; - if(chnklen<6)error(1,"E: Header chunk too short."); - if(chnklen>6)error(0,"W: Header chunk length longer than expected. Ignoring extra bytes."); - fmt=readSW();trk=readSW();divs=readSW(); - if(divs&0x8000)error(1,"E: SMTPE format is not supported."); - for(;byteread<chnklen;++byteread){fgetc(f);} + int chnklen = readDW(); + byteread = 0; + if (chnklen < 6)error(1, "E: Header chunk too short."); + if (chnklen > 6)error(0, "W: Header chunk length longer than expected. Ignoring extra bytes."); + fmt = readSW(); + trk = readSW(); + divs = readSW(); + if (divs & 0x8000)error(1, "E: SMTPE format is not supported."); + for (; byteread < chnklen; ++byteread) + { + fgetc(f); + } } int CMidiFile::chunkReader(int hdrXp) { - char hdr[6]; - if(!fgets(hdr,5,f))error(1,"E: Unexpected EOF."); - if(hdrXp) - if(strncmp(hdr,"MThd",4)){error(1,"E: Wrong MIDI header.");throw;} - else return headerChunkReader(),0; - else - if(strncmp(hdr,"MTrk",4)) - { - error(0,"W: Wrong track chunk header. Ignoring the whole chunk."); - for(int chnklen=readDW();chnklen>0;--chnklen)fgetc(f);return 0; - } - else return trackChunkReader(),1; -} -CMidiFile::CMidiFile(const char* fn) -{ - title=copyright=NULL;notes=eventc=0;std=0;valid=1; - try - { - if(!(f=fopen(fn,"rb")))throw (fprintf(stderr,"E: file %s doesn't exist!\n",fn),2); - chunkReader(1); - for(uint32_t i=0;i<trk;i+=chunkReader(0)); - printf("%d note(s)\n",notes); - fclose(f); - std::sort(eventList,eventList+eventc,cmp); - } - catch(int){fprintf(stderr,"E: %s is not a supported file.\n",fn);valid=0;} + char hdr[6]; + if (!fgets(hdr, 5, f))error(1, "E: Unexpected EOF."); + if (hdrXp) + if (strncmp(hdr, "MThd", 4)) + { + error(1, "E: Wrong MIDI header."); + throw; + } + else return headerChunkReader(), 0; + else if (strncmp(hdr, "MTrk", 4)) + { + error(0, "W: Wrong track chunk header. Ignoring the whole chunk."); + for (int chnklen = readDW(); chnklen > 0; --chnklen)fgetc(f); + return 0; + } + else return trackChunkReader(), 1; +} +CMidiFile::CMidiFile(const char *fn) +{ + title = copyright = NULL; + notes = eventc = 0; + std = 0; + valid = 1; + try + { + if (!(f = fopen(fn, "rb")))throw (fprintf(stderr, "E: file %s doesn't exist!\n", fn), 2); + chunkReader(1); + for (uint32_t i = 0; i < trk; i += chunkReader(0)); + printf("%d note(s)\n", notes); + fclose(f); + std::sort(eventList, eventList + eventc, cmp); + } + catch (int) + { + fprintf(stderr, "E: %s is not a supported file.\n", fn); + valid = 0; + } } CMidiFile::~CMidiFile() { - for(uint32_t i=0;i<eventc;++i)delete eventList[i]; - if(title)delete[] title;if(copyright)delete[] copyright; -} -const SEvent* CMidiFile::getEvent(uint32_t id){return id<eventc?eventList[id]:NULL;} -uint32_t CMidiFile::getEventCount(){return eventc;} -uint32_t CMidiFile::getDivision(){return divs;} -uint32_t CMidiFile::getNoteCount(){return notes;} -uint32_t CMidiFile::getStandard(){return std;} -bool CMidiFile::isValid(){return valid;} -const char* CMidiFile::getTitle(){return title;} -const char* CMidiFile::getCopyright(){return copyright;} + for (uint32_t i = 0; i < eventc; ++i)delete eventList[i]; + if (title)delete[] title; + if (copyright)delete[] copyright; +} +const SEvent *CMidiFile::getEvent(uint32_t id) +{ + return id < eventc ? eventList[id] : NULL; +} +uint32_t CMidiFile::getEventCount() +{ + return eventc; +} +uint32_t CMidiFile::getDivision() +{ + return divs; +} +uint32_t CMidiFile::getNoteCount() +{ + return notes; +} +uint32_t CMidiFile::getStandard() +{ + return std; +} +bool CMidiFile::isValid() +{ + return valid; +} +const char *CMidiFile::getTitle() +{ + return title; +} +const char *CMidiFile::getCopyright() +{ + return copyright; +} |