From b03133b80b268c74d1dd5c92e2af6907b51c91b2 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Thu, 22 Jun 2017 11:26:48 +0800 Subject: Minor bug fixes. SMF reader finally takes chunk length into account. Do not prepend sysex header to F0h sysex. Let the readers do it. File readers code cleanups and refined error messages. --- core/qmpmidioutrtmidi.cpp | 2 +- core/qmpmidiplay.cpp | 26 +++----------- core/qmpmidiread.cpp | 92 +++++++++++++++++++++++------------------------ 3 files changed, 50 insertions(+), 70 deletions(-) (limited to 'core') diff --git a/core/qmpmidioutrtmidi.cpp b/core/qmpmidioutrtmidi.cpp index 295e87b..7f75fda 100644 --- a/core/qmpmidioutrtmidi.cpp +++ b/core/qmpmidioutrtmidi.cpp @@ -69,8 +69,8 @@ void qmpMidiOutRtMidi::panic(uint8_t ch) } void qmpMidiOutRtMidi::reset(uint8_t ch) { - basicMessage(0xB0|ch,120,0); basicMessage(0xB0|ch,121,0); + basicMessage(0xB0|ch,123,0); } void qmpMidiOutRtMidi::onMapped(uint8_t,int) { diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp index c3df381..55b3959 100644 --- a/core/qmpmidiplay.cpp +++ b/core/qmpmidiplay.cpp @@ -69,27 +69,10 @@ bool CMidiPlayer::processEvent(const SEvent *e) break; } } - if((e->type&0x0F)==0x00||(e->type&0x0F)==07) - { - if(sendSysEx) - { - int l=e->p1;char *rmsg; - if(e->type&0x0F==0x00) - { - rmsg=(char*)malloc((++l)*sizeof(char)); - rmsg[0]=0xF0;rmsg[1]=0; - } - else - { - rmsg=(char*)malloc(l*sizeof(char)); - rmsg[0]=0; - } - strcat(rmsg,e->str.c_str()); - for(auto& i:mididev) - if(i.refcnt) - i.dev->extendedMessage(l,rmsg); - } - } + if(((e->type&0x0F)==0x00||(e->type&0x0F)==07)&&sendSysEx) + for(auto& i:mididev) + if(i.refcnt) + i.dev->extendedMessage(e->p1,e->str.c_str()); return false; } return false; @@ -298,6 +281,7 @@ bool CMidiPlayer::playerLoadFile(const char* fn) 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]) diff --git a/core/qmpmidiread.cpp b/core/qmpmidiread.cpp index cd3ffa3..6089ac5 100644 --- a/core/qmpmidiread.cpp +++ b/core/qmpmidiread.cpp @@ -14,21 +14,20 @@ 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"; void CSMFReader::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 std::runtime_error("fatal error"); + va_list ap;char buf[1024],bufr[1024]; + va_start(ap,format);vsnprintf(buf,1024,format,ap);va_end(ap); + snprintf(bufr,1024,"%s at %#lx",buf,ftell(f)); + if(fatal)throw std::runtime_error(bufr); + else fprintf(stderr,"CSMFReader W: %s.\n",bufr); } uint32_t CSMFReader::readSW() { - 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 CSMFReader::readDW() { - byteread+=4; uint32_t ret=0; for(int i=0;i<4;++i){ret<<=8;ret|=((uint32_t)fgetc(f))&0xFF;} return ret; @@ -39,18 +38,17 @@ uint32_t CSMFReader::readVL() do { t=fgetc(f); - if(++c>4)error(1,"E: Variable length type overflow."); + if(++c>4)error(1,"Variable length type overflow"); ret<<=7;ret|=(t&0x7F); }while(t&0x80); - byteread+=c; return ret; } int CSMFReader::eventReader()//returns 0 if End of Track encountered { uint32_t delta=readVL();curt+=delta; - char type=fgetc(f);++byteread;uint32_t p1,p2; + char type=fgetc(f);uint32_t p1,p2; static char lasttype;eventdiscarded=0; - if(!(type&0x80)){fseek(f,-1,SEEK_CUR);--byteread;type=lasttype;} + if(!(type&0x80)){fseek(f,-1,SEEK_CUR);type=lasttype;} switch(type&0xF0) { case 0x80://Note Off @@ -58,29 +56,28 @@ int CSMFReader::eventReader()//returns 0 if End of Track encountered case 0xA0://Note Aftertouch case 0xB0://Controller Change case 0xE0://Pitch wheel - p1=fgetc(f);p2=fgetc(f);byteread+=2; + p1=fgetc(f);p2=fgetc(f); curTrack->appendEvent(SEvent(curid,curt,type,p1,p2)); break; case 0xC0://Patch Change case 0xD0://Channel Aftertouch - p1=fgetc(f);++byteread; + p1=fgetc(f); curTrack->appendEvent(SEvent(curid,curt,type,p1,0)); break; case 0xF0: if((type&0x0F)==0x0F)//Meta Event { - char metatype=fgetc(f);++byteread; + char metatype=fgetc(f); 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; + fgetc(f);fgetc(f); break; case 0x2F://End of Track - fgetc(f);++byteread; + fgetc(f); return 0; break; case 0x51://Set Tempo @@ -90,16 +87,13 @@ int CSMFReader::eventReader()//returns 0 if End of Track encountered 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(); + fgetc(f);p1=readDW(); curTrack->appendEvent(SEvent(curid,curt,type,metatype,p1)); break; case 0x59://Key signature - fgetc(f);++byteread; - p1=readSW(); + fgetc(f);p1=readSW(); curTrack->appendEvent(SEvent(curid,curt,type,metatype,p1)); break; case 0x01:case 0x02:case 0x03: @@ -109,9 +103,7 @@ int CSMFReader::eventReader()//returns 0 if End of Track encountered uint32_t len=readVL(),c;char* str=NULL; if(len<=1024&&len>0)str=new char[len+8]; for(c=0;cappendEvent(SEvent(curid,curt,type,metatype,0,str)); if(str&&metatype==0x03&&!ret->title) @@ -135,9 +127,9 @@ int CSMFReader::eventReader()//returns 0 if End of Track encountered if((type&0x0F)==0x00) { str[0]=0xF0;++len; - for(c=1;cappendEvent(SEvent(curid,curt,type,len,0,str)); if(!strcmp(str,GM1SysX))ret->std=1; if(!strcmp(str,GM2SysX))ret->std=2; @@ -145,10 +137,10 @@ int CSMFReader::eventReader()//returns 0 if End of Track encountered if(!strcmp(str,XGSysEx))ret->std=4; delete[] str; } - else error(0,"W: Unknown event type %#x",type); + else error(0,"Unknown event type %#x",type); break; default: - error(0,"W: Unknown event type %#x",type); + error(0,"Unknown event type %#x",type); } lasttype=type;++curid; if(curTrack->eventList.size()) @@ -163,50 +155,49 @@ void CSMFReader::trackChunkReader() { ret->tracks.push_back(CMidiTrack()); curTrack=&ret->tracks.back(); - int chnklen=readDW();byteread=0;curt=0;curid=0; - while(/*bytereadchnklen) - { - error(1,"E: Read past end of track."); - }*/ + if(byteread>chnklen) + error(1,"Read past end of track"); } void CSMFReader::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."); + int chnklen=readDW();byteread=ftell(f); + if(chnklen<6)error(1,"Header chunk too short"); + if(chnklen>6)error(0,"Header chunk length longer than expected. Ignoring extra bytes"); fmt=readSW();trk=readSW();ret->divs=readSW(); - if(ret->divs&0x8000)error(1,"E: SMTPE format is not supported."); - for(;bytereaddivs&0x8000)error(1,"SMTPE format is not supported"); + for(byteread=ftell(f)-byteread;byteread0;--chnklen)fgetc(f);return 0; + error(0,"Wrong track chunk header. Ignoring the whole chunk"); + uint32_t chnklen=readDW();fseek(f,chnklen,SEEK_CUR);return 0; } else return trackChunkReader(),1; } @@ -220,12 +211,17 @@ CMidiFile* CSMFReader::readFile(const char* fn) ret->title=ret->copyright=NULL;ret->std=0;ret->valid=1; try { - if(!(f=fopen(fn,"rb")))throw (fprintf(stderr,"E: file %s doesn't exist!\n",fn),std::runtime_error("File doesn't exist")); + if(!(f=fopen(fn,"rb"))) + throw std::runtime_error("File doesn't exist"); chunkReader(1); for(uint32_t i=0;ivalid=0;if(f)fclose(f);f=NULL;} + catch(std::runtime_error& e) + { + fprintf(stderr,"CSMFReader E: %s is not a supported file. Cause: %s.\n",fn,e.what()); + ret->valid=0;if(f)fclose(f);f=NULL; + } return ret; } CSMFReader::~CSMFReader() -- cgit v1.2.3