jdkmidi class library documentation

Copyright © 2004 J.D. Koftinoff Software, Ltd.

Released under the GNU General Public License (GPL)




Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

src/jdkmidi_fileread.cpp

Go to the documentation of this file.
00001 /*
00002  *  libjdkmidi-2004 C++ Class Library for MIDI
00003  *
00004  *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
00005  *  www.jdkoftinoff.com
00006  *  jeffk@jdkoftinoff.com
00007  *
00008  *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 /*
00025 **  Copyright 1986 to 1998 By J.D. Koftinoff Software, Ltd.
00026 **
00027 **  All rights reserved.
00028 **
00029 **  No one may duplicate this source code in any form for any reason
00030 **  without the written permission given by J.D. Koftinoff Software, Ltd.
00031 **
00032 */
00033 
00034 #include "jdkmidi/world.h"
00035 
00036 #include "jdkmidi/fileread.h"
00037 
00038 // TO DO: decide which way is right for this flag and fix it - The standard midi file format specs are (were?) unclear
00039 
00040 #define MIDIFRD_ALLOW_STATUS_ACROSS_META_EVENT  0
00041 
00042 namespace jdkmidi
00043 {
00044   
00045   
00046   void  MIDIFileEvents::UpdateTime( MIDIClockTime delta_time )  
00047   {
00048     
00049   } 
00050   
00051   void  MIDIFileEvents::ChanMessage( const MIDITimedMessage &msg )  
00052   {
00053     
00054     switch( msg.GetStatus()&0xf0 )
00055     {
00056     case NOTE_OFF:
00057       mf_note_off( msg );
00058       break;
00059     case NOTE_ON:
00060       if( msg.GetVelocity()==0 )
00061       {
00062         mf_note_off( msg );
00063       }
00064       else
00065       {
00066         mf_note_on( msg );
00067       }
00068       break;
00069     case POLY_PRESSURE:
00070       mf_poly_after( msg );
00071       break;
00072     case CONTROL_CHANGE:
00073       if( msg.GetByte2()>C_ALL_NOTES_OFF )
00074       {
00075         mf_system_mode( msg );
00076       }
00077       else
00078       {
00079         mf_control( msg );
00080       }
00081       break;
00082     case PROGRAM_CHANGE:
00083       mf_program( msg );
00084       break;
00085     case CHANNEL_PRESSURE:
00086       mf_chan_after( msg );
00087       break;
00088     case PITCH_BEND:
00089       mf_bender( msg );
00090       break;
00091       
00092     } 
00093   } 
00094   
00095   void  MIDIFileEvents::MetaEvent(MIDIClockTime time, int type, int leng, unsigned char *m )  
00096   {
00097     
00098     switch  ( type ) {
00099     case MF_SEQUENCE_NUMBER:
00100       mf_seqnum( time, To16Bit( m[0], m[1] ) );
00101       break;
00102     case MF_TEXT_EVENT:
00103     case MF_COPYRIGHT:
00104     case MF_TRACK_NAME:
00105     case MF_INSTRUMENT_NAME:
00106     case MF_LYRIC:
00107     case MF_MARKER:
00108     case MF_CUE_POINT:
00109     case MF_GENERIC_TEXT_8:
00110     case MF_GENERIC_TEXT_9:
00111     case MF_GENERIC_TEXT_A:
00112     case MF_GENERIC_TEXT_B:
00113     case MF_GENERIC_TEXT_C:
00114     case MF_GENERIC_TEXT_D:
00115     case MF_GENERIC_TEXT_E:
00116     case MF_GENERIC_TEXT_F:
00117       
00118       // These are all text events
00119       
00120       m[leng]=0;      // make sure string ends in NULL
00121       mf_text(time,type, leng, m );
00122       break;
00123     case MF_OUTPUT_CABLE:
00124       // TO DO:
00125       break;
00126     case MF_TRACK_LOOP:
00127       // TO DO:
00128       break;
00129     case MF_END_OF_TRACK:      // End of Track
00130       mf_eot( time );
00131       break;
00132       
00133     case MF_TEMPO:      // Set Tempo
00134       mf_tempo( time, To32Bit(0,m[0],m[1],m[2]) );
00135       break;
00136       
00137     case MF_SMPTE:
00138       mf_smpte( time, m[0],m[1],m[2],m[3],m[4]);
00139       break;
00140       
00141     case MF_TIMESIG:
00142       mf_timesig( time, m[0],m[1],m[2],m[3]);
00143       break;
00144       
00145     case MF_KEYSIG:
00146     {
00147       char c=m[0];
00148       mf_keysig(time, c,m[1]);
00149     }
00150     break;
00151     
00152     case MF_SEQUENCER_SPECIFIC:
00153       mf_sqspecific(time, leng,m);
00154       break;
00155       
00156     default:
00157       mf_metamisc(time, type,leng,m);
00158       break;
00159     }
00160   } 
00161   
00162   void    MIDIFileEvents::mf_starttrack( int trk )  
00163   {
00164     
00165   } 
00166   
00167   void    MIDIFileEvents::mf_endtrack( int trk )  
00168   {
00169     
00170   } 
00171   
00172   void    MIDIFileEvents::mf_eot( MIDIClockTime time )  
00173   {
00174     
00175   } 
00176   
00177   void    MIDIFileEvents::mf_error( char *s ) 
00178   {
00179     
00180   } 
00181   
00182   void    MIDIFileEvents::mf_header(
00183     int a, 
00184     int b, 
00185     int c ) 
00186   {
00187     
00188   } 
00189   
00190   void    MIDIFileEvents::mf_arbitrary(
00191     MIDIClockTime time,
00192     int a, 
00193     unsigned char *s )  
00194   {
00195     
00196   } 
00197   
00198   void    MIDIFileEvents::mf_metamisc(  
00199     MIDIClockTime time,
00200     int a, 
00201     int b, 
00202     unsigned char *s )  
00203   {
00204     
00205   } 
00206   
00207   void    MIDIFileEvents::mf_seqnum(    
00208     MIDIClockTime time,
00209     int a)  
00210   {
00211     
00212   } 
00213   
00214   void    MIDIFileEvents::mf_smpte( 
00215     MIDIClockTime time,
00216     int a, 
00217     int b, 
00218     int c, 
00219     int d, 
00220     int e)  
00221   {
00222     
00223   } 
00224   
00225   void    MIDIFileEvents::mf_timesig(   
00226     MIDIClockTime time,
00227     int a, 
00228     int b, 
00229     int c, 
00230     int d ) 
00231   {
00232     
00233   } 
00234   
00235   void    MIDIFileEvents::mf_tempo( 
00236     MIDIClockTime time,
00237     unsigned long a)  
00238   {
00239     
00240   } 
00241   
00242   void    MIDIFileEvents::mf_keysig( 
00243     MIDIClockTime time,
00244     int a,
00245     int b)  
00246   {
00247     
00248   } 
00249   
00250   void    MIDIFileEvents::mf_sqspecific( 
00251     MIDIClockTime time,
00252     int a,
00253     unsigned char *s )  
00254   {
00255     
00256   } 
00257   
00258   void    MIDIFileEvents::mf_text(
00259     MIDIClockTime time,
00260     int a, 
00261     int b, 
00262     unsigned char *s )  
00263   {
00264     
00265   } 
00266   
00267   void    MIDIFileEvents::mf_system_mode(const MIDITimedMessage &msg  ) 
00268   {
00269     
00270   } 
00271   
00272   void    MIDIFileEvents::mf_note_on(const MIDITimedMessage &msg  ) 
00273   {
00274     
00275   } 
00276   
00277   void    MIDIFileEvents::mf_note_off(const MIDITimedMessage &msg   ) 
00278   {
00279     
00280   } 
00281   
00282   void    MIDIFileEvents::mf_poly_after(const MIDITimedMessage &msg   ) 
00283   {
00284     
00285   } 
00286   
00287   void    MIDIFileEvents::mf_bender(const MIDITimedMessage &msg   ) 
00288   {
00289     
00290   } 
00291   
00292   void    MIDIFileEvents::mf_program(const MIDITimedMessage &msg  ) 
00293   {
00294     
00295   } 
00296   
00297   void    MIDIFileEvents::mf_chan_after(const MIDITimedMessage &msg   ) 
00298   {
00299     
00300   } 
00301   
00302   void    MIDIFileEvents::mf_control(const MIDITimedMessage &msg  ) 
00303   {
00304     
00305   } 
00306   
00307   void    MIDIFileEvents::mf_sysex(
00308     MIDIClockTime time,
00309     const MIDISystemExclusive &ex 
00310     ) 
00311   {
00312     
00313   } 
00314   
00315   
00316   
00317   
00318   
00319   MIDIFileRead::MIDIFileRead( 
00320     MIDIFileReadStream *input_stream_,
00321     MIDIFileEvents *event_handler_,
00322     unsigned long max_msg_len_ 
00323     ) 
00324     : 
00325     input_stream( input_stream_ ),
00326     event_handler( event_handler_ )
00327   {
00328     no_merge=0;
00329     cur_time=0;
00330     skip_init=1;
00331     to_be_read=0;
00332     msg_index=0;
00333     cur_track=0;
00334     abort_parse=0;
00335     max_msg_len=max_msg_len_;
00336     the_msg = new unsigned char[max_msg_len];
00337   } 
00338   
00339   MIDIFileRead::~MIDIFileRead() 
00340   {
00341     delete [] the_msg;
00342   } 
00343   
00344   void MIDIFileRead::mf_error( char *e )  
00345   {
00346     event_handler->mf_error(e);
00347     abort_parse=true;   
00348   } 
00349   
00350   bool MIDIFileRead::Parse()  
00351   {
00352     int n;
00353     
00354     n = ReadHeader();
00355     if( n <=0 )
00356     {
00357       mf_error( "No Tracks" );
00358       return false;
00359     }
00360     for( cur_track=0; cur_track<n; cur_track++ )
00361     {
00362       ReadTrack();
00363       if( abort_parse )
00364       {
00365         return false;
00366       }
00367     }
00368     return true;
00369   } 
00370   
00371   int MIDIFileRead::ReadMT( unsigned long type, int skip )  
00372   {
00373     unsigned long read=0;
00374     int c;       
00375     
00376     read=OSTYPE( EGetC(), EGetC(), EGetC(), EGetC() );
00377     if( type!=read )
00378     {
00379       if( skip )
00380       {
00381         do
00382         {
00383           read<<=8;
00384           c=EGetC();
00385           read|=c;
00386           if( read==type )
00387             return true;
00388           if( abort_parse )
00389             return false;
00390           
00391         } while( c!=-1 );
00392       }
00393       mf_error( "Error looking for chunk type" );
00394       return false;
00395     }
00396     else
00397     {
00398       return true;
00399     }
00400     
00401   } 
00402   
00403   int MIDIFileRead::ReadHeader()  
00404   {
00405     int   the_format;
00406     int  ntrks;
00407     int   division;
00408     
00409     if( ReadMT( _MThd, skip_init )==0xffff )
00410       return 0;
00411     
00412     if( abort_parse )
00413       return 0;
00414     
00415     to_be_read = Read32Bit();
00416     the_format=Read16Bit();
00417     ntrks=Read16Bit();
00418     division=Read16Bit();
00419     
00420     if( abort_parse )
00421       return 0;
00422     
00423     
00424     header_format=the_format;
00425     header_ntrks=ntrks;
00426     header_division=division;
00427     
00428     event_handler->mf_header( the_format, ntrks, division );
00429     
00430     
00431     // printf( "\nto be read = %d\n", to_be_read );
00432     
00433     while( to_be_read > 0 )
00434       EGetC();
00435     
00436     return ntrks;
00437   } 
00438   
00439 //
00440 // read a track chunk
00441 //
00442   
00443   void MIDIFileRead::ReadTrack()  
00444   {
00445     //
00446     // This array is indexed by the high half of a status byte.  Its
00447     // value is either the number of bytes needed (1 or 2) for a channel
00448     // message, or 0 (meaning it's not  a channel message).
00449     //
00450     
00451     static char chantype[] = 
00452       {
00453         0, 0, 0, 0, 0, 0, 0, 0,         // 0x00 through 0x70
00454         2, 2, 2, 2, 1, 1, 2, 0          // 0x80 through 0xf0
00455       };
00456     
00457     unsigned long lookfor, lng;
00458     int c, c1, type;
00459     int sysexcontinue=0; // 1 if last message was unfinished sysex
00460     int running=0;       // 1 when running status used
00461     int status=0;                // (possible running) status byte
00462     int needed;
00463     
00464     
00465     if( ReadMT( _MTrk, 0) == 0xffff )
00466       return;
00467     
00468     to_be_read=Read32Bit();
00469     cur_time=0;
00470     
00471     event_handler->mf_starttrack( cur_track );
00472     
00473     while( to_be_read > 0 && !abort_parse )
00474     {
00475       unsigned long deltat=ReadVariableNum();
00476       
00477       event_handler->UpdateTime( deltat );
00478       
00479       cur_time += deltat;
00480       
00481       c=EGetC();
00482       
00483       if( c==-1 )
00484         break;
00485       
00486       if( sysexcontinue && c!=0xf7 )
00487         mf_error( "Error after expected continuation of SysEx" );
00488       
00489       if( (c&0x80)==0 )
00490       {
00491         if( status==0 )
00492           mf_error( "Unexpected Running Status" );
00493         running=1;
00494         needed = chantype[ (status>>4) & 0xf ];
00495       }
00496       else
00497       {
00498         // TO DO: is running status to be cleared or not when meta event happens?
00499         
00500 #if MIDIFRD_ALLOW_STATUS_ACROSS_META_EVENT
00501         if(  c!=0xff )
00502         {
00503           status=c;
00504           running=0;
00505           needed=0;
00506         }
00507         
00508 #else
00509         status=c;
00510         running=0;
00511         needed = chantype[ (status>>4) & 0xf ]; 
00512 #endif
00513         
00514       }
00515       
00516       
00517       
00518       if( needed )            // ie. is it a channel message?
00519       {
00520         if( running )
00521           c1=c;
00522         else
00523           c1=EGetC();
00524         FormChanMessage( (unsigned char)status, (unsigned char)c1, (unsigned char)((needed>1) ? EGetC() : 0 ));
00525         continue;
00526       }
00527       
00528       
00529       switch( c )
00530       {
00531       case 0xff:              // meta-event
00532         type=EGetC();
00533         lng = ReadVariableNum();
00534         
00535         lookfor = to_be_read - lng;
00536         
00537         MsgInit();
00538         while( to_be_read > lookfor)
00539         {
00540           MsgAdd( EGetC() );
00541         }
00542         
00543         event_handler->MetaEvent( cur_time, type, msg_index, the_msg );
00544         break;
00545         
00546       case 0xf0:              // start of sys-ex
00547         lng = ReadVariableNum();
00548         lookfor = to_be_read - lng;
00549         
00550         MsgInit();
00551         MsgAdd(0xf0);
00552         
00553         while( to_be_read>lookfor )
00554           MsgAdd( c=EGetC() );
00555         
00556         if( c==0xf7 || no_merge==0 )
00557         {
00558           // make a sysex object out of the raw sysex data
00559           // the buffer is not to be deleted upon destruction of ex
00560           
00561           MIDISystemExclusive ex(
00562             the_msg,
00563             msg_index,
00564             msg_index,
00565             false
00566             );
00567           
00568           // give the sysex object to our event handler
00569           
00570           event_handler->mf_sysex( cur_time, ex );
00571         }
00572         else
00573           sysexcontinue=1; // merge into next msg
00574         break;
00575       case 0xf7:              // sysex continuation or 
00576         // arbitary stuff
00577         lng=ReadVariableNum();
00578         lookfor = to_be_read - lng;
00579         
00580         if( ! sysexcontinue )
00581           MsgInit();
00582         
00583         while( to_be_read > lookfor )
00584           MsgAdd(c=EGetC());
00585         
00586         if( !sysexcontinue )
00587         {
00588           event_handler->mf_arbitrary( cur_time, msg_index, the_msg );
00589         }
00590         else if( c== 0xf7 )
00591         {
00592           // make a sysex object out of the raw sysex data
00593           // the buffer is not to be deleted upon destruction of ex
00594           
00595           MIDISystemExclusive ex(
00596             the_msg,
00597             msg_index,
00598             msg_index,
00599             false
00600             );
00601           event_handler->mf_sysex( cur_time, ex );
00602           sysexcontinue=0;
00603         }
00604         break;
00605       default:
00606         BadByte(c);
00607         break;
00608       }
00609     }
00610     event_handler->mf_endtrack( cur_track );
00611     return;
00612   } 
00613   
00614   unsigned long MIDIFileRead::ReadVariableNum() 
00615   {
00616     unsigned long value;
00617     int c;
00618     
00619     c=EGetC();
00620     if( c==-1 )
00621     {
00622       return 0;
00623     }
00624     value = c;
00625     
00626     if( c & 0x80 )
00627     {
00628       value &= 0x7f;
00629       do
00630       {
00631         c=EGetC();
00632         value =  (value<<7) + (c&0x7f);
00633       } while( c&0x80 );
00634     }
00635     return value;
00636   } 
00637   
00638   unsigned long MIDIFileRead::Read32Bit() 
00639   {
00640     int c1, c2, c3, c4;
00641     
00642     c1=EGetC();
00643     c2=EGetC();
00644     c3=EGetC();
00645     c4=EGetC();
00646     
00647     return To32Bit( (unsigned char)c1, (unsigned char)c2, (unsigned char)c3, (unsigned char)c4 );
00648   } 
00649   
00650   int MIDIFileRead::Read16Bit() 
00651   {
00652     int c1, c2;
00653     
00654     c1=EGetC();
00655     c2=EGetC();
00656     
00657     return To16Bit( (unsigned char)c1, (unsigned char)c2 );
00658   } 
00659   
00660   int MIDIFileRead::EGetC() 
00661   {
00662     int c;
00663     
00664     c = input_stream->ReadChar();
00665     
00666     
00667     if( c<0 )
00668     {
00669       mf_error( "Unexpected Stream Error" );
00670       abort_parse=true;
00671       return -1;
00672     }
00673     
00674     --to_be_read;
00675     
00676     return (int)c;
00677   } 
00678   
00679   void MIDIFileRead::MsgAdd( int a )  
00680   {
00681     if( msg_index<max_msg_len )
00682       the_msg[ msg_index++ ] = (unsigned char)a;
00683   } 
00684   
00685   void MIDIFileRead::MsgInit()  
00686   {
00687     msg_index=0;
00688   } 
00689   
00690   void MIDIFileRead::BadByte( int c ) 
00691   {
00692     mf_error( "Unexpected Byte" );
00693     abort_parse=true;
00694   } 
00695   
00696   void MIDIFileRead::FormChanMessage( unsigned char st, unsigned char b1, unsigned char b2 )  
00697   {
00698     MIDITimedMessage m;
00699     
00700     m.SetStatus( st );
00701     m.SetByte1( b1 );
00702     m.SetByte2( b2 );
00703     m.SetTime( cur_time );
00704     
00705     if( st>=0x80 && st<0xf0 )
00706     {
00707       event_handler->ChanMessage(m);
00708     }
00709     
00710   } 
00711   
00712   
00713 }