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 | |
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')
-rw-r--r-- | midifmt-plugin/midifmt-plugin.pro | 27 | ||||
-rw-r--r-- | midifmt-plugin/midifmtplugin.cpp | 111 | ||||
-rw-r--r-- | midifmt-plugin/midifmtplugin.hpp | 45 |
3 files changed, 183 insertions, 0 deletions
diff --git a/midifmt-plugin/midifmt-plugin.pro b/midifmt-plugin/midifmt-plugin.pro new file mode 100644 index 0000000..e063dac --- /dev/null +++ b/midifmt-plugin/midifmt-plugin.pro @@ -0,0 +1,27 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-02-09T09:24:43 +# +#------------------------------------------------- + +QT -= core gui + +CONFIG += c++11 + +TARGET = midifmt-plugin +TEMPLATE = lib + +DEFINES += MIDIFMTPLUGIN_LIBRARY + +SOURCES += midifmtplugin.cpp + +HEADERS += midifmtplugin.hpp + +unix { + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O3 + QMAKE_LFLAGS_RELEASE -= -O1 + QMAKE_LFLAGS_RELEASE += -O3 + target.path = $$PREFIX/lib/qmidiplayer + INSTALLS += target +} 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";} diff --git a/midifmt-plugin/midifmtplugin.hpp b/midifmt-plugin/midifmtplugin.hpp new file mode 100644 index 0000000..f6284dd --- /dev/null +++ b/midifmt-plugin/midifmtplugin.hpp @@ -0,0 +1,45 @@ +#ifndef MIDIFMTPLUGIN_HPP +#define MIDIFMTPLUGIN_HPP + +#include <cstdio> +#include "../include/qmpcorepublic.hpp" + +class CMidiStreamReader:public IMidiFileReader +{ + private: + CMidiFile* ret; + FILE* f; + int eventdiscarded,fmt; + uint32_t readDWLE(); + bool RIFFHeaderReader(); + bool midsBodyReader(); + public: + CMidiStreamReader(); + ~CMidiStreamReader(); + CMidiFile* readFile(const char *fn); + void discardCurrentEvent(); + void commitEventChange(SEventCallBackData d); +}; + +class qmpMidiFmtPlugin:public qmpPluginIntf +{ + private: + CMidiStreamReader* mdsreader; + public: + static qmpPluginAPI* api; + qmpMidiFmtPlugin(qmpPluginAPI* _api); + ~qmpMidiFmtPlugin(); + void init(); + void deinit(); + const char* pluginGetName(); + const char* pluginGetVersion(); +}; + +extern "C"{ + EXPORTSYM qmpPluginIntf* qmpPluginGetInterface(qmpPluginAPI* api) + {return new qmpMidiFmtPlugin(api);} + EXPORTSYM const char* qmpPluginGetAPIRev() + {return QMP_PLUGIN_API_REV;} +} + +#endif // MIDIFMTPLUGIN_HPP |