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/qmpmidiread.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 'qmidiplayer-lite/qmpmidiread.cpp')
-rw-r--r-- | qmidiplayer-lite/qmpmidiread.cpp | 525 |
1 files changed, 320 insertions, 205 deletions
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; +} |