MIDIReader.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "MIDIReader.hxx"
00025 #include "MIDISong.hxx"
00026 #include "MIDITrack.hxx"
00027
00028 namespace MIDI
00029 {
00030
00031 void Reader::Read(Song& s)
00032
00033 {
00034 static int nbytesPerChnMsg[7] =
00035 { 3,3,3,3,2,3,3 };
00036
00037 ChunkType chnkType = GetChunkType();
00038 unsigned int length;
00039 unsigned short format,ntrcks;
00040
00041 if (chnkType!="MThd") throw Error("Expected a header chunk\n");
00042
00043 length = GetInt();
00044 if (length!=6)
00045 throw Error("Unexpected header chunk length\n");
00046
00047 format = GetShort();
00048 if (format!=0 && format!=1)
00049 throw Error("Unsupported MIDI file format\n");
00050
00051 ntrcks = GetShort();
00052
00053 s.SetTicksPerQ(GetShort());
00054
00055 for (int i=0;i<ntrcks;i++)
00056 {
00057 chnkType = GetChunkType();
00058 if (chnkType!="MTrk") throw Error("Expected a track chunk\n");
00059
00060 int chnkLength = GetInt();
00061
00062 Byte runningStatus = 0;
00063 Ticks t = 0;
00064 Track *track = new Track;
00065 s.AddTrack(track);
00066
00067 mCnt = 0;
00068
00069 while (mCnt!=chnkLength)
00070 {
00071 unsigned int dt = GetVarLength();
00072 t += dt;
00073 Byte b = GetByte();
00074 if (b & 0x80)
00075 {
00076 int type = ((b&0xF0)>>4)-8;
00077 if (type==7)
00078 {
00079 if (b == 0xFF)
00080 {
00081 Byte metaType = GetByte();
00082 unsigned int length = GetVarLength();
00083 if (metaType!=0x2F)
00084 {
00085 MetaEvent* ev = new MetaEvent(Message(b,metaType),t,length);
00086
00087 track->Add(ev);
00088
00089 for (unsigned int i=0;i<length;i++)
00090 ev->mData[i] = GetByte();
00091
00092 if (metaType == 3)
00093 {
00094 track->Name(ev->mData,length);
00095 }
00096 }
00097 }
00098 else if (b == 0xF0 || b==0xF7)
00099 {
00100
00101 int length = GetVarLength();
00102 while (--length)
00103 {
00104 GetByte();
00105 }
00106 if (GetByte()!=0xF7)
00107 {
00108 throw Error("SysEx message did not terminate with 0xF7");
00109 }
00110 }
00111 else
00112 {
00113 throw Error("Encountered a message that I don't know how to handle");
00114 }
00115 runningStatus = 0;
00116 }else{
00117 if (nbytesPerChnMsg[type]==2)
00118 {
00119 Byte b1 = GetByte();
00120 track->Add(new Event(Message(b,b1),t));
00121 }
00122 else
00123 {
00124 Byte b1 = GetByte();
00125 Byte b2 = GetByte();
00126 track->Add(new Event(Message(b,b1,b2),t));
00127 }
00128 runningStatus = b;
00129 }
00130 }else{
00131 int type = ((runningStatus&0xF0)>>4)-8;
00132 if (nbytesPerChnMsg[type]==2)
00133 {
00134 track->Add(new Event(Message(runningStatus,b),t));
00135 }
00136 else
00137 {
00138 Byte b2 = GetByte();
00139 track->Add(new Event(Message(runningStatus,b,b2),t));
00140 }
00141 }
00142 }
00143 }
00144 }
00145
00146 }
00147