diff options
author | Chris Xiong <chirs241097@gmail.com> | 2017-02-09 16:04:43 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2017-02-09 16:04:43 +0800 |
commit | 620aad63042e0f397ea6691fe92ac40fcc6b6fed (patch) | |
tree | b36a0f0c00ffba03bfed9513a360b7ecf442e720 /midifmt-plugin/midifmtplugin.cpp | |
parent | 1976c49f835267d33ef88bd3fc20d18363e12c0b (diff) | |
download | QMidiPlayer-620aad63042e0f397ea6691fe92ac40fcc6b6fed.tar.xz |
Add extra midi formats support via the file reader API.
Fix note counting.
Diffstat (limited to 'midifmt-plugin/midifmtplugin.cpp')
-rw-r--r-- | midifmt-plugin/midifmtplugin.cpp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/midifmt-plugin/midifmtplugin.cpp b/midifmt-plugin/midifmtplugin.cpp new file mode 100644 index 0000000..33e636e --- /dev/null +++ b/midifmt-plugin/midifmtplugin.cpp @@ -0,0 +1,111 @@ +#include <cstring> +#include <algorithm> +#include <stdexcept> +#include "midifmtplugin.hpp" +qmpPluginAPI* qmpMidiFmtPlugin::api=NULL; + +uint32_t CMidiStreamReader::readDWLE() +{ + uint32_t ret=0; + for(uint32_t i=0;i<4;++i)ret|=((uint32_t)fgetc(f))<<(i<<3); + return ret; +} +bool CMidiStreamReader::RIFFHeaderReader() +{ + char hdr[9]; + fread(hdr,1,4,f); + if(strncmp(hdr,"RIFF",4))return false; + fseek(f,4,SEEK_CUR); + fread(hdr,1,8,f); + if(strncmp(hdr,"MIDSfmt ",8))return false; + if(readDWLE()!=0x0C)return false; + ret->divs=readDWLE(); + readDWLE(); + fmt=readDWLE(); + return true; +} +bool CMidiStreamReader::midsBodyReader() +{ + char buf[9]; + fread(buf,1,4,f); + if(strncmp(buf,"data",4))return false; + readDWLE();//size + uint32_t cblocks=readDWLE(); + uint32_t curid=0,cts=0; + for(int i=0;i<cblocks;++i) + { + readDWLE(); + uint32_t blocksz=readDWLE(),cpos=ftell(f); + while(ftell(f)-cpos<blocksz) + { + cts+=readDWLE(); + if(!(fmt&1))readDWLE(); + uint32_t e=readDWLE(); + SEvent ev; + if(e>>24==1)//set tempo + ev=SEvent(curid,cts,0xFF,0x51,e&0x00FFFFFF); + else if(e>>24==0)//midishortmsg + ev=SEvent(curid,cts,e&0xFF,(e>>8)&0xFF,(e>>16)&0xFF); + else return false; + //fprintf(stderr,"ev: @ %x t %x p1 %x p2 %x\n",ev.time,ev.type,ev.p1,ev.p2); + if((ev.type&0xF0)==0x90&&ev.p2==0)//Note on with zero velo + ev.type=(ev.type&0x0F)|0x80; + if((ev.type&0xF0)==0xE0)//pitch wheel + {ev.p1=(ev.p1|(ev.p2<<7))&0x3FFF;ev.p2=0;} + ret->eventList.push_back(ev);eventdiscarded=0; + qmpMidiFmtPlugin::api->callEventReaderCB(SEventCallBackData(ev.type,ev.p1,ev.p2,ev.time)); + if(eventdiscarded)ret->eventList.pop_back(); + ++curid; + } + } + return true; +} +CMidiFile* CMidiStreamReader::readFile(const char *fn) +{ + ret=new CMidiFile; + ret->title=ret->copyright=NULL;ret->std=0;ret->valid=1; + try + { + if(!(f=fopen(fn,"rb")))throw std::runtime_error("File doesn't exist"); + if(!RIFFHeaderReader())throw std::runtime_error("Wrong RIFF header"); + if(!midsBodyReader())throw std::runtime_error("MIDS data error"); + std::sort(ret->eventList.begin(),ret->eventList.end()); + }catch(std::runtime_error& e){fprintf(stderr,"MIDI Format plugin: E: %s is not a supported file. Cause: %s.\n",fn,e.what());ret->valid=0;fclose(f);f=NULL;} + return ret; +} +void CMidiStreamReader::discardCurrentEvent() +{ + eventdiscarded=1; +} +void CMidiStreamReader::commitEventChange(SEventCallBackData d) +{ + ret->eventList[ret->eventList.size()-1].time=d.time; + ret->eventList[ret->eventList.size()-1].type=d.type; + ret->eventList[ret->eventList.size()-1].p1=d.p1; + ret->eventList[ret->eventList.size()-1].p2=d.p2; +} +CMidiStreamReader::CMidiStreamReader() +{ + ret=NULL;f=NULL; +} +CMidiStreamReader::~CMidiStreamReader() +{ +} + +qmpMidiFmtPlugin::qmpMidiFmtPlugin(qmpPluginAPI *_api) +{api=_api;} +qmpMidiFmtPlugin::~qmpMidiFmtPlugin() +{api=NULL;} +void qmpMidiFmtPlugin::init() +{ + api->registerFileReader(mdsreader=new CMidiStreamReader,"MIDS reader"); +} +void qmpMidiFmtPlugin::deinit() +{ + api->unregisterFileReader("MIDS reader"); + delete mdsreader; +} +const char* qmpMidiFmtPlugin::pluginGetName() +{return "QMidiPlayer extra midi formats plugin";} +const char* qmpMidiFmtPlugin::pluginGetVersion() +{return "0.8.5";} |