zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit af0cd14c6307eb570e215173e9bda71ecf0d0204
parent c5e5c3b2efa0a8e2d1fef23294d4a2af21f640e9
Author: paulnasca <paulnasca>
Date:   Sat, 27 Mar 2004 12:22:42 +0000

*** empty log message ***

Diffstat:
Msrc/Seq/MIDIFile.C | 200++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/Seq/MIDIFile.h | 25+++++++++++++++++++++----
2 files changed, 198 insertions(+), 27 deletions(-)

diff --git a/src/Seq/MIDIFile.C b/src/Seq/MIDIFile.C @@ -83,10 +83,6 @@ int MIDIFile::parsemidifile(){ int ntracks=getint16();//this is always if the format is "0" printf("ntracks %d\n",ntracks); - if (ntracks>=NUM_MIDI_CHANNELS){ - ntracks=NUM_MIDI_CHANNELS; - }; - int division=getint16(); printf("division %d\n",division); if (division>=0){//delta time units in each a quater note @@ -95,16 +91,23 @@ int MIDIFile::parsemidifile(){ printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); }; -// for (int n=0;n<ntracks;n++){ - if (parsetrack(0)<0) { + for (int n=0;n<ntracks;n++){ + if (parsetrack(n)<0) { clearmidifile(); return(-1); }; -// }; + }; + + printf("\n\nCURRENT File position is = 0x%x\n",midifilek); + printf("\nMIDI file succesfully parsed.\n"); +// printf("\n0x%x\n",getbyte()); return(0); }; +//private members + + int MIDIFile::parsetrack(int ntrack){ printf("\n--==*Reading track %d **==--\n",ntrack); @@ -112,26 +115,145 @@ int MIDIFile::parsetrack(int ntrack){ if (chunk!=0x4d54726b) return(-1); int size=getint32(); - printf("%d\n",size); + printf("size = %d\n",size); + + int oldmidifilek=midifilek; + + unsigned char lastmsg=0; + unsigned int dt=0; + + while(!midieof){ + unsigned int msgdeltatime=getvarint32(); + + dt+=msgdeltatime; + + int msg=peekbyte(); + printf("raw msg=0x%x ",msg); + if (msg<0x80) { + msg=lastmsg; + } else { + lastmsg=msg; + getbyte(); + }; + printf("msg=0x%x\n",msg); + + unsigned int mtype,mlength; + + switch(msg){ + case 0x80 ... 0x8f://note on off + parsenoteon(msg & 0x0f,dt); + dt=0; + break; + case 0x90 ... 0x9f://note on (or note off) + parsenoteon(msg & 0x0f,dt); + dt=0; + break; + case 0xa0 ... 0xaf://aftertouch - ignored + skipnbytes(2); + break; + case 0xb0 ... 0xbf://control change + parsecontrolchange(msg & 0x0f,dt); + dt=0; + break; + case 0xc0 ... 0xcf://program change - ignored + skipnbytes(1); + break; + case 0xd0 ... 0xdf://channel pressure - ignored + skipnbytes(1); + break; + case 0xe0 ... 0xef://channel mode messages + skipnbytes(2); + break; + case 0xf0://sysex - ignored + while (getbyte()!=0xf7){ + if (midieof) break; + }; + break; + case 0xf7://sysex (another type) - ignored + skipnbytes(getvarint32()); + break; + + case 0xff://meta-event + mtype=getbyte(); + mlength=getbyte(); + parsemetaevent(mtype,mlength); + break; + + default: + getbyte(); + printf("UNKNOWN message! 0x%x\n",msg); + return(-1); + break; + }; + + if (midieof) return(-1); + + dt=msgdeltatime; + + if ((midifilek-oldmidifilek)==size) break; + else if((midifilek-oldmidifilek)>size) return(-1); // if (size!=6) return(-1);//header is always 6 bytes long -/* -unsigned long ReadVarLen( void ) { - unsigned long value; - byte c; - - if ((value = getc(infile)) & 0x80) { - value &= 0x7f; - do { - value = (value << 7) + ((c = getc(infile)) & 0x7f); - } while (c & 0x80); - } - return value; -} + }; -*/ + printf("End Track\n\n"); + + return(0); +}; + + +void MIDIFile::parsenoteoff(char chan,unsigned int dt){ + unsigned char note,vel; + note=getbyte(); + + if (chan>=NUM_MIDI_CHANNELS) return; + + printf("Note off:%d ",note); +}; + +void MIDIFile::parsenoteon(char chan,unsigned int dt){ + unsigned char note,vel; + note=getbyte(); + vel=getbyte(); + + if (chan>=NUM_MIDI_CHANNELS) return; + + printf("[dt %d ] Note on:%d %d\n",dt,note,vel); +}; + +void MIDIFile::parsecontrolchange(char chan,unsigned int dt){ + unsigned char control,value; + control=getbyte(); + value=getbyte(); + + if (chan>=NUM_MIDI_CHANNELS) return; + + printf("[dt %d] Control change:%d %d\n",dt,control,value); + +}; + +void MIDIFile::parsepitchwheel(char chan, unsigned int dt){ + unsigned char valhi,vallo; + vallo=getbyte(); + valhi=getbyte(); + + if (chan>=NUM_MIDI_CHANNELS) return; + + int value=(int)valhi*128+vallo; + + printf("[dt %d] Pitch wheel:%d\n",dt,value); + +}; + +void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength){ + int oldmidifilek=midifilek; + printf("meta-event type=0x%x length=%d\n",mtype,mlength); + + + + midifilek=oldmidifilek+mlength; + }; -//private members void MIDIFile::clearmidifile(){ if (midifile!=NULL) delete(midifile); @@ -153,6 +275,14 @@ unsigned char MIDIFile::getbyte(){ return(midifile[midifilek++]); }; +unsigned char MIDIFile::peekbyte(){ + if (midifilek>=midifilesize) { + midieof=true; + return(0); + }; + return(midifile[midifilek]); +}; + unsigned int MIDIFile::getint32(){ unsigned int result=0; for (int i=0;i<4;i++) { @@ -170,3 +300,27 @@ unsigned short int MIDIFile::getint16(){ if (midieof) result=0; return(result); }; + +unsigned int MIDIFile::getvarint32(){ + unsigned long result=0; + unsigned char b; + + if ((result = getbyte()) & 0x80) { + result &= 0x7f; + do { + b=getbyte(); + result = (result << 7) + (b & 0x7f); + }while (b & 0x80); + } + return result; +}; + + +void MIDIFile::skipnbytes(int n){ + midifilek+=n; + if (midifilek>=midifilesize){ + midifilek=midifilesize-1; + midieof=true; + }; +}; + diff --git a/src/Seq/MIDIFile.h b/src/Seq/MIDIFile.h @@ -36,25 +36,42 @@ class MIDIFile{ //returns -1 if there is an error, otherwise 0 int parsemidifile(); - //returns -1 if there is an error, otherwise 0 - int parsetrack(int ntrack); - private: unsigned char *midifile; int midifilesize,midifilek; bool midieof; + + //returns -1 if there is an error, otherwise 0 + int parsetrack(int ntrack); + + void parsenoteoff(char chan,unsigned int dt); + void parsenoteon(char chan,unsigned int dt); + void parsecontrolchange(char chan,unsigned int dt); + void parsepitchwheel(char chan, unsigned int dt); + void parsemetaevent(unsigned char mtype,unsigned char mlength); void clearmidifile(); + /* Low Level MIDIfile functions */ + //get a byte from the midifile unsigned char getbyte(); + + //peek the current byte from the midifile + unsigned char peekbyte(); //get a set of 4 bytes from the midifile unsigned int getint32(); //get a word of 2 bytes from the midifile unsigned short int getint16(); - + + //read a variable length quantity + unsigned int getvarint32(); + + //skip some bytes + void skipnbytes(int n); + struct { double tick;//how many seconds one tick has }data;