MIDIWriter.cxx
Go to the documentation of this file.00001 #include "MIDITrack.hxx"
00002 #include "MIDISong.hxx"
00003 #include "MIDIWriter.hxx"
00004
00005 namespace MIDI
00006 {
00007 Writer::Writer(const char* filename)
00008 : mFile(0)
00009 , mBytesWritten(0)
00010 {
00011 mFile = fopen(filename,"wb");
00012 }
00013
00014 Writer::~Writer()
00015 {
00016 }
00017
00018 void Writer::Write(Song& s)
00019 {
00020 if(!mFile) return;
00021
00022 static int nbytesPerChnMsg[7] = { 3,3,3,3,2,3,3 };
00023
00024 mTracks = s.Tracks();
00025 mFormat = (mTracks > 1) ? 1 : 0;
00026 mDivision = (int)s.GetTicksPerQ();
00027
00028 WriteHeader();
00029
00030 unsigned long trkhdr=MTrk;
00031 long offset,endt;
00032 unsigned t0,t1;
00033 for(int i=0; i < mTracks; i++)
00034 {
00035
00036 Write32Bit(trkhdr);
00037
00038 offset = ftell(mFile);
00039 Write32Bit(0);
00040 mBytesWritten=0;
00041 t0=t1=0;
00042 Track* track = s.GetTrack(i);
00043 Track::EventIterator it = track->Begin();
00044 for(;it != track->End(); it++)
00045 {
00046 const Event &ev = **it;
00047 t1=(unsigned)ev.GetTicks();
00048 int type = ((ev[0]&0xF0)>>4)-8;
00049 if(type==7)
00050 {
00051 if(ev[0]==0xFF && ev[1]==0x51)
00052 {
00053
00054 WriteVarLen(t1-t0);
00055 WriteCh(0xFF);
00056 WriteCh(0x51);
00057 WriteCh(0x03);
00058 MetaEvent* e = (MetaEvent*)*it;
00059 for(int k=0; k < 3; k++)
00060 {
00061 WriteCh(e->mData[k]);
00062 }
00063 }
00064 }
00065 else
00066 {
00067 WriteVarLen(t1-t0);
00068 int msglen = nbytesPerChnMsg[type];
00069 for(int j=0; j < msglen; j++)
00070 {
00071 WriteCh((char)ev[j]);
00072 }
00073 }
00074 t0=t1;
00075
00076 }
00077
00078 WriteCh(0);
00079 WriteCh((unsigned)0xFF);
00080 WriteCh((unsigned)0x2f);
00081 WriteCh(0);
00082 endt = ftell(mFile);
00083 fseek(mFile,offset,0);
00084
00085 Write32Bit(mBytesWritten);
00086
00087 fseek(mFile,endt,0);
00088 }
00089 fclose(mFile);
00090 }
00091
00092 void Writer::WriteHeader()
00093 {
00094 unsigned long id=MThd;
00095
00096 Write32Bit(id);
00097 Write32Bit(6);
00098 Write16Bit(mFormat);
00099 Write16Bit(mTracks);
00100 Write16Bit(mDivision);
00101 }
00102
00103 void Writer::WriteVarLen(register unsigned long value)
00104 {
00105 register unsigned long buffer;
00106 buffer = value & 0x7F;
00107
00108 while( (value >>= 7) )
00109 {
00110 buffer <<= 8;
00111 buffer |= ((value & 0x7F) | 0x80);
00112 }
00113
00114 while(1)
00115 {
00116 WriteCh(buffer);
00117 if (buffer & 0x80)
00118 buffer >>= 8;
00119 else
00120 break;
00121 }
00122 }
00123
00124 void Writer::Write32Bit(unsigned long data)
00125 {
00126 WriteCh((unsigned)((data >> 24) & 0xff));
00127 WriteCh((unsigned)((data >> 16) & 0xff));
00128 WriteCh((unsigned)((data >> 8 ) & 0xff));
00129 WriteCh((unsigned)(data & 0xff));
00130 }
00131
00132 void Writer::Write16Bit(int data)
00133 {
00134 WriteCh((unsigned)((data & 0xff00) >> 8));
00135 WriteCh((unsigned)(data & 0xff));
00136 }
00137
00138 void Writer::WriteCh(char c)
00139 {
00140 fputc(c,mFile);
00141 mBytesWritten++;
00142 }
00143 }
00144
00145
00146