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_advancedsequencer.cpp

Go to the documentation of this file.
00001 #include "jdkmidi/world.h"
00002 #include "jdkmidi/advancedsequencer.h"
00003 
00004 
00005 namespace jdkmidi
00006 {
00007   static void FixQuotes( char *s_ )
00008   {
00009     unsigned char *s = (unsigned char *)s_;
00010     while( *s )
00011     {
00012       if( *s==0xd2 || *s==0xd3 )
00013       {
00014         *s='"';
00015       }
00016       else if( *s==0xd5 )
00017       {
00018         *s='\'';
00019       }
00020       else if( *s>=0x80 )
00021       {
00022         *s = ' ';
00023       }
00024       s++;
00025     }
00026   }
00027   
00028   AdvancedSequencer::AdvancedSequencer()
00029     :
00030     thru_processor(2),
00031     thru_transposer(),
00032     thru_rechannelizer(),
00033     driver(256,stdout),
00034     tracks(17),
00035     notifier( stdout ),
00036     seq( &tracks, &notifier ),
00037     mgr( &driver, &notifier, &seq ),
00038     repeat_start_measure(0),
00039     repeat_end_measure(0),
00040     repeat_play_mode(false),
00041     num_warp_positions(0),
00042     file_loaded(false),
00043     chain_mode(false)
00044   {
00045   }
00046   
00047   AdvancedSequencer::~AdvancedSequencer()
00048   {
00049     Stop();
00050     CloseMIDI();
00051     
00052     for( int i=0; i<num_warp_positions; ++i )
00053     {
00054       delete warp_positions[i];
00055     }
00056   }
00057   
00058   
00059   
00060   bool AdvancedSequencer::OpenMIDI( int in_port, int out_port, int timer_resolution )
00061   {
00062 #if 0
00063     CloseMIDI();
00064     
00065     if( !driver.StartTimer( timer_resolution ) )
00066     {
00067       return false;
00068     }
00069     
00070     if( in_port!=-1 )
00071     {
00072       driver.OpenMIDIInPort( in_port );
00073     }
00074     
00075     if( driver.OpenMIDIOutPort( out_port ) )
00076     {
00077       return true;
00078     }
00079     else
00080     {
00081       return false;
00082     }
00083 #else
00084     return true;
00085 #endif
00086   }
00087   
00088   
00089   void AdvancedSequencer::CloseMIDI()
00090   {
00091     Stop();
00092 #if 0
00093     driver.StopTimer();
00094     driver.AllNotesOff();
00095     Sleep(100);
00096     driver.CloseMIDIInPort();
00097     driver.CloseMIDIOutPort();
00098 #endif
00099   }
00100   
00101   
00102   void AdvancedSequencer::SetMIDIThruEnable( bool f )
00103   {
00104     driver.SetThruEnable( f );
00105   }
00106   
00107   bool AdvancedSequencer::GetMIDIThruEnable() const
00108   {
00109     return driver.GetThruEnable();
00110   }
00111   
00112   void AdvancedSequencer::SetMIDIThruChannel( int chan )
00113   {
00114     thru_rechannelizer.SetAllRechan( chan );
00115     driver.AllNotesOff();
00116     
00117   }
00118   
00119   
00120   int AdvancedSequencer::GetMIDIThruChannel() const
00121   {
00122     return thru_rechannelizer.GetRechanMap( 0 );
00123   }
00124   
00125   
00126   
00127   void AdvancedSequencer::SetMIDIThruTranspose( int val )
00128   {
00129     thru_transposer.SetAllTranspose( val );
00130     driver.AllNotesOff();
00131   }
00132   
00133   
00134   int AdvancedSequencer::GetMIDIThruTranspose() const
00135   {
00136     return thru_transposer.GetTransposeChannel( 0 );
00137   }
00138   
00139   
00140   
00141   bool AdvancedSequencer::Load( const char *fname )
00142   {
00143     char realname[1024];
00144     
00145     strcpy( realname, fname );
00146     int orignamelen = strlen(fname);
00147     
00148     chain_mode =false;
00149     if( orignamelen>0 )
00150     {
00151       if( realname[orignamelen-1]=='+' )
00152       {
00153         realname[orignamelen-1]=0;
00154         chain_mode = true;
00155       }
00156     }
00157     
00158     MIDIFileReadStreamFile mfreader_stream( realname );
00159     MIDIFileReadMultiTrack track_loader( &tracks );
00160     MIDIFileRead reader( &mfreader_stream, &track_loader );
00161     
00162     Stop();
00163     driver.AllNotesOff();
00164     
00165     tracks.Clear();
00166     seq.ResetAllTracks();
00167     
00168     if( reader.Parse() )
00169     {
00170       file_loaded=true;
00171       
00172       Reset();
00173       
00174       GoToMeasure( 0 );
00175       ExtractWarpPositions();
00176       
00177     }
00178     else
00179     {
00180       file_loaded=false;
00181     }
00182     return file_loaded;
00183   }
00184   
00185   
00186   void AdvancedSequencer::Reset()
00187   {
00188     Stop();
00189     driver.AllNotesOff();
00190     UnmuteAllTracks();
00191     UnSoloTrack();
00192     SetTempoScale( 1.00 );
00193     
00194     seq.ResetAllTracks();
00195     GoToMeasure( 0 );
00196     
00197   }
00198   
00199   void AdvancedSequencer::GoToTime( MIDIClockTime t )
00200   {
00201     if( mgr.IsSeqPlay() )
00202     {
00203       Stop();
00204       seq.GoToTime( t+1 );
00205       Play();
00206     }
00207     else
00208     {
00209       seq.GoToTime( t+1 );
00210     }
00211     
00212   }
00213   
00214   
00215   void AdvancedSequencer::GoToMeasure( int measure, int beat )
00216   {
00217     if( !file_loaded )
00218     {
00219       return;
00220     }
00221     // figure out which warp item we use
00222     // try warp to the last warp point BEFORE the
00223     // requested measure
00224     
00225     int warp_to_item = (measure-1) / MEASURES_PER_WARP;
00226     
00227     
00228     if( warp_to_item >= num_warp_positions )
00229       warp_to_item = num_warp_positions-1;
00230     
00231     if( warp_to_item<0 )
00232       warp_to_item=0;
00233     
00234     
00235     if( mgr.IsSeqPlay() )
00236     {
00237       Stop();
00238       
00239       if( warp_positions[warp_to_item] )
00240       {
00241         seq.SetState( warp_positions[warp_to_item] );
00242       }
00243       seq.GoToMeasure( measure, beat );
00244       Play();
00245     }
00246     else
00247     {
00248       if( warp_positions[warp_to_item] )
00249       {
00250         seq.SetState( warp_positions[warp_to_item] );
00251       }
00252       
00253       seq.GoToMeasure( measure, beat );
00254       for( int i=0; i<seq.GetNumTracks(); ++i )
00255       {
00256         seq.GetTrackState(i)->note_matrix.Clear();
00257       }
00258     }
00259   }
00260   
00261   
00262   void AdvancedSequencer::Play( int clock_offset )
00263   {
00264     if( !file_loaded )
00265     {
00266       return;
00267     }
00268     
00269     Stop();
00270     
00271     for( int i=0; i<seq.GetNumTracks(); ++i )
00272     {
00273       seq.GetTrackState(i)->note_matrix.Clear();
00274     }
00275     
00276     
00277     if( repeat_play_mode )
00278     {
00279       seq.GoToMeasure( repeat_start_measure );
00280     }
00281     
00282     MIDIClockTime cur_time = seq.GetCurrentMIDIClockTime();
00283     
00284     if( (long)cur_time>-clock_offset )
00285       cur_time+=clock_offset;
00286     
00287     seq.GoToTime( cur_time );
00288     
00289     mgr.SetSeqOffset( (unsigned long)seq.GetCurrentTimeInMs() );
00290     mgr.SetTimeOffset( 0 );
00291     
00292     mgr.SeqPlay();
00293   }
00294   
00295   
00296   
00297   void AdvancedSequencer::RepeatPlay( bool enable, int start_measure, int end_measure )
00298   {
00299     if( !file_loaded )
00300     {
00301       return;
00302     }
00303     
00304     if( start_measure < end_measure && start_measure>=0 )
00305     {
00306       repeat_play_mode = enable;
00307       repeat_start_measure = start_measure;
00308       repeat_end_measure = end_measure;
00309     }
00310     else
00311     {
00312       repeat_play_mode = false;
00313     }
00314     
00315     mgr.SetRepeatPlay(
00316       repeat_play_mode,
00317       repeat_start_measure,
00318       repeat_end_measure
00319       );
00320   }
00321   
00322   
00323   void AdvancedSequencer::Pause()
00324   {
00325     if( !file_loaded )
00326     {
00327       return;
00328     }
00329     Stop();
00330   }
00331   
00332   
00333   void AdvancedSequencer::Stop()
00334   {
00335     if( !file_loaded )
00336     {
00337       return;
00338     }
00339     if( !mgr.IsSeqStop() )
00340     {
00341       mgr.SeqStop();
00342 
00343       driver.AllNotesOff();
00344       for( int i=0; i<seq.GetNumTracks(); ++i )
00345       {
00346         seq.GetTrackState(i)->note_matrix.Clear();
00347       }
00348       
00349     }
00350   }
00351   
00352   
00353   
00354   void AdvancedSequencer::UnmuteAllTracks()
00355   {
00356     if( !file_loaded )
00357     {
00358       return;
00359     }
00360     for( int i=0; i<seq.GetNumTracks(); ++i )
00361     {
00362       if( seq.GetTrackProcessor(i)->mute )
00363       {
00364         seq.GetTrackState(i)->note_matrix.Clear();
00365         seq.GetTrackProcessor(i)->mute = false;
00366       }
00367     }
00368     
00369     driver.AllNotesOff();
00370   }
00371   
00372   void AdvancedSequencer::SoloTrack( int trk )
00373   {
00374     if( !file_loaded )
00375     {
00376       return;
00377     }
00378     if( trk==-1 )
00379     {
00380       seq.SetSoloMode(false);
00381       driver.AllNotesOff();
00382       
00383       for( int i=0; i<seq.GetNumTracks(); ++i )
00384       {
00385         seq.GetTrackState(i)->note_matrix.Clear();
00386       }
00387     }
00388     else
00389     {
00390       seq.SetSoloMode(true,trk);
00391       driver.AllNotesOff();
00392       
00393       for( int i=0; i<seq.GetNumTracks(); ++i )
00394       {
00395         seq.GetTrackState(i)->note_matrix.Clear();
00396       }
00397       
00398     }
00399   }
00400   
00401   
00402   void AdvancedSequencer::UnSoloTrack()
00403   {
00404     if( !file_loaded )
00405     {
00406       return;
00407     }
00408     seq.SetSoloMode( false );
00409     driver.AllNotesOff();
00410     for( int i=0; i<seq.GetNumTracks(); ++i )
00411     {
00412       seq.GetTrackState(i)->note_matrix.Clear();
00413     }
00414   }
00415   
00416   
00417   void AdvancedSequencer::SetTrackMute( int trk, bool f )
00418   {
00419     if( !file_loaded )
00420     {
00421       return;
00422     }
00423     seq.GetTrackProcessor(trk)->mute = f;
00424     driver.AllNotesOff();
00425   }
00426   
00427   
00428   
00429   void AdvancedSequencer::SetTempoScale( double scale )
00430   {
00431     if( !file_loaded )
00432     {
00433       return;
00434     }
00435     seq.SetCurrentTempoScale( scale );
00436   }
00437   
00438   
00439   double AdvancedSequencer::GetTempoWithoutScale() const
00440   {
00441     return seq.GetCurrentTempo();
00442   }
00443   
00444   
00445   double AdvancedSequencer::GetTempoWithScale() const
00446   {
00447     return seq.GetCurrentTempo() * seq.GetCurrentTempoScale();
00448   }
00449   
00450   
00451   
00452   int AdvancedSequencer::GetMeasure() const
00453   {
00454     if( !file_loaded )
00455     {
00456       return 0;
00457     }
00458     
00459     return seq.GetCurrentMeasure();
00460   }
00461   
00462   
00463   int AdvancedSequencer::GetBeat() const
00464   {
00465     if( !file_loaded )
00466     {
00467       return 0;
00468     }
00469     
00470     return seq.GetCurrentBeat();
00471   }
00472   
00473   
00474   
00475   int AdvancedSequencer::GetTimeSigNumerator() const
00476   {
00477     if( !file_loaded )
00478     {
00479       return 4;
00480     }
00481     return seq.GetTrackState(0)->timesig_numerator;
00482   }
00483   
00484   
00485   int AdvancedSequencer::GetTimeSigDenominator() const
00486   {
00487     if( !file_loaded )
00488     {
00489       return 4;
00490     }
00491     
00492     return seq.GetTrackState(0)->timesig_denominator;
00493   }
00494   
00495   
00496   
00497   int AdvancedSequencer::GetTrackNoteCount( int trk ) const
00498   {
00499     if( !file_loaded )
00500     {
00501       return 0;
00502     }
00503     
00504     if( mgr.IsSeqStop() )
00505     {
00506       return 0;
00507     }
00508     else
00509     {
00510       return seq.GetTrackState(trk)->note_matrix.GetTotalCount();
00511     }
00512   }
00513   
00514   
00515   const char *AdvancedSequencer::GetTrackName( int trk ) const
00516   {
00517     if( !file_loaded )
00518     {
00519       return "";
00520     }
00521     
00522     return seq.GetTrackState(trk)->track_name;
00523   }
00524   
00525   
00526   int AdvancedSequencer::GetTrackVolume( int trk ) const
00527   {
00528     if( !file_loaded )
00529     {
00530       return 100;
00531     }
00532     
00533     return seq.GetTrackState(trk)->volume;
00534   }
00535   
00536   
00537   
00538   void AdvancedSequencer::SetTrackVelocityScale( int trk, int scale )
00539   {
00540     if( !file_loaded )
00541     {
00542       return;
00543     }
00544     
00545     seq.GetTrackProcessor(trk)->velocity_scale = scale;
00546   }
00547   
00548   
00549   int AdvancedSequencer::GetTrackVelocityScale( int trk ) const
00550   {
00551     if( !file_loaded )
00552     {
00553       return 100;
00554     }
00555     
00556     return seq.GetTrackProcessor(trk)->velocity_scale;
00557   }
00558   
00559   
00560   
00561   void AdvancedSequencer::SetTrackRechannelize( int trk, int chan )
00562   {
00563     if( !file_loaded )
00564     {
00565       return;
00566     }
00567     
00568     seq.GetTrackProcessor(trk)->rechannel = chan;
00569     driver.AllNotesOff();
00570     seq.GetTrackState(trk)->note_matrix.Clear();
00571     
00572   }
00573   
00574   
00575   int AdvancedSequencer::GetTrackRechannelize( int trk ) const
00576   {
00577     if( !file_loaded )
00578     {
00579       return -1;
00580     }
00581     
00582     
00583     return seq.GetTrackProcessor(trk)->rechannel;
00584   }
00585   
00586   
00587   
00588   void AdvancedSequencer::SetTrackTranspose( int trk, int trans )
00589   {
00590     if( !file_loaded )
00591     {
00592       return;
00593     }
00594     
00595     bool was_playing=mgr.IsSeqPlay();
00596     
00597     if( mgr.IsSeqPlay() )
00598     {
00599       was_playing=true;
00600       mgr.SeqStop();
00601     }
00602     
00603     if( trk==-1 )
00604     {
00605       for( trk=0; trk<tracks.GetNumTracks(); ++trk )
00606       {
00607         seq.GetTrackProcessor(trk)->transpose = trans;
00608       }
00609     }
00610     else
00611     {
00612       seq.GetTrackProcessor(trk)->transpose = trans;
00613     }
00614     
00615     if( was_playing )
00616     {
00617 #if 0
00618       driver.ResetMIDIOut();
00619       driver.AllNotesOff();
00620 #endif
00621       seq.GetTrackState(trk)->note_matrix.Clear();
00622       
00623       mgr.SeqPlay();
00624     }
00625     
00626   }
00627   
00628   
00629   int AdvancedSequencer::GetTrackTranspose( int trk ) const
00630   {
00631     if( !file_loaded )
00632     {
00633       return 0;
00634     }
00635     
00636     return seq.GetTrackProcessor(trk)->transpose;
00637   }
00638   
00639   
00640   
00641   
00642   void AdvancedSequencer::ExtractMarkers( std::vector< std::string > *list )
00643   {
00644     if( !file_loaded )
00645     {
00646       list->clear();
00647       num_markers=0;
00648       return;
00649     }
00650     
00651     MIDITrack *t = tracks.GetTrack(0);
00652     
00653     list->clear();
00654     int cnt=0;
00655     
00656     int measure=0;
00657     int beat=0;
00658     
00659     int timesig_numerator=4;
00660     int timesig_denominator=4;
00661     
00662     MIDIClockTime last_beat_time=0;
00663     MIDIClockTime last_event_time=0;
00664     int clks_per_beat=tracks.GetClksPerBeat();
00665     
00666     for( int i=0; i<t->GetNumEvents(); ++i )
00667     {
00668       MIDITimedBigMessage *m = t->GetEventAddress(i);
00669       
00670       if( m )
00671       {
00672         // how many beats have gone by since the last event?
00673         
00674         long beats_gone_by = (m->GetTime()-last_beat_time)/clks_per_beat;
00675         
00676         if( beats_gone_by>0 )
00677         {
00678           // calculate what our new measure/beat is
00679           beat += beats_gone_by;
00680           // carry over beat overflow to measure
00681           measure += beat/timesig_numerator;
00682           beat = beat%timesig_numerator;
00683           last_beat_time += (clks_per_beat * beats_gone_by);
00684         }
00685         
00686         
00687         if( m->IsMetaEvent() && m->IsTimeSig() )
00688         {
00689           timesig_numerator = m->GetTimeSigNumerator();
00690           timesig_denominator = m->GetTimeSigDenominator();
00691           clks_per_beat=tracks.GetClksPerBeat() * 4 / timesig_denominator;
00692         }
00693         
00694         if( m->IsTextEvent() && m->GetSysEx() )
00695         {
00696           if( (m->GetMetaType() == META_GENERIC_TEXT )
00697               || m->GetMetaType() == META_MARKER_TEXT
00698               || m->GetMetaType() == META_CUE_TEXT )
00699           {
00700             char buf[256];
00701             char line[256];
00702             
00703             memcpy( buf, m->GetSysEx()->GetBuf(), m->GetSysEx()->GetLength() );
00704             buf[ m->GetSysEx()->GetLength() ] = '\0';
00705             FixQuotes( buf );
00706             
00707             sprintf( line, "%03d:%d        %s", measure+1, beat+1, buf );
00708             list->push_back( std::string(line) );
00709             marker_times[ cnt++ ] = m->GetTime();
00710           }
00711         }
00712         
00713         last_event_time = m->GetTime();
00714       }
00715     }
00716     num_markers = cnt;
00717   }
00718   
00719   
00720   int AdvancedSequencer::GetCurrentMarker() const
00721   {
00722     if( !file_loaded )
00723     {
00724       return -1;
00725     }
00726     
00727     // find marker with largest time that
00728     // is before cur_time
00729     
00730     MIDIClockTime cur_time = seq.GetCurrentMIDIClockTime();
00731     
00732     cur_time+=20;
00733     
00734     int last=-1;
00735     
00736     for( int i=0; i<num_markers; ++i )
00737     {
00738       if( marker_times[i] > cur_time )
00739       {
00740         break;
00741       }
00742       else
00743       {
00744         last=i;
00745       }
00746     }
00747     return last;
00748   }
00749   
00750   
00751   
00752   int AdvancedSequencer::FindFirstChannelOnTrack(int trk)
00753   {
00754     if( !file_loaded )
00755     {
00756       return -1;
00757     }
00758     
00759     int first_channel = -1;
00760     
00761     MIDITrack *t = tracks.GetTrack(trk);
00762     
00763     if( t )
00764     {
00765       // go through all events
00766       // until we find a channel message
00767       // and then return the channel number plus 1
00768       
00769       for( int i=0; i<t->GetNumEvents(); ++i )
00770       {
00771         MIDITimedBigMessage *m = t->GetEventAddress(i);
00772         
00773         if( m )
00774         {
00775           if( m->IsChannelMsg() )
00776           {
00777             first_channel = m->GetChannel() + 1;
00778             break;
00779           }
00780         }
00781       }
00782       
00783     }
00784     
00785     return first_channel;
00786   }
00787   
00788   
00789   void AdvancedSequencer::ExtractWarpPositions()
00790   {
00791     if( !file_loaded )
00792     {
00793       for( int i=0; i<num_warp_positions; ++i )
00794       {
00795         delete warp_positions[i];
00796       }
00797       num_warp_positions=0;
00798       return;
00799     }
00800     
00801     Stop();
00802     
00803     // delete all our current warp positions
00804     
00805     for( int i=0; i<num_warp_positions; ++i )
00806     {
00807       delete warp_positions[i];
00808     }
00809     num_warp_positions=0;
00810     
00811     
00812     
00813     while(num_warp_positions<MAX_WARP_POSITIONS)
00814     {
00815       if( !seq.GoToMeasure( num_warp_positions*MEASURES_PER_WARP, 0 ) )
00816       {
00817         break;
00818       }
00819       
00820       // save current sequencer state at this position
00821       warp_positions[num_warp_positions++] =
00822         new MIDISequencerState(
00823           *seq.GetState()
00824           );
00825     }
00826     
00827     seq.GoToMeasure( 0,0 );
00828   }
00829   
00830 }