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                         // write track header
00036                         Write32Bit(trkhdr);
00037                         // remember position
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                                                 // write tempo information
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); // write delta time
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                         // write end of track
00078                         WriteCh(0);
00079                         WriteCh((unsigned)0xFF);
00080                         WriteCh((unsigned)0x2f);
00081                         WriteCh(0);
00082                         endt = ftell(mFile);
00083                         fseek(mFile,offset,0);
00084                         // write track length
00085                         Write32Bit(mBytesWritten);
00086                         // retrieve position
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);            // MThd 
00097                 Write32Bit(6);             // header length = 6
00098                 Write16Bit(mFormat);   // format 
00099                 Write16Bit(mTracks);   // ntracks 
00100                 Write16Bit(mDivision); // division
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 // END
00146 
Generated by  doxygen 1.6.3