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