void MIDISequencer::ScanEventsAtThisTime()
{
    // save the current iterator state
    MIDIMultiTrackIteratorState istate ( state.iterator.GetState() );
    int prev_measure = state.cur_measure;
    int prev_beat = state.cur_beat;
    // process all messages up to and including this time only
    MIDIClockTime orig_clock = state.cur_clock;
    double orig_time_ms = state.cur_time_ms;
    MIDIClockTime t = 0;
    int trk;
    MIDITimedBigMessage ev;

    while (
        GetNextEventTime ( &t )
        && t == orig_clock
        && GetNextEvent ( &trk, &ev )
    )
    {
        ;
    }

    // restore the iterator state
    state.iterator.SetState ( istate );
    // and current time
    state.cur_clock = orig_clock;
    state.cur_time_ms = float ( orig_time_ms );
    state.cur_measure = prev_measure;
    state.cur_beat = prev_beat;
}
bool MIDISequencer::GetNextEventTimeMs ( double *t )
{
    MIDIClockTime ct;
    bool f = GetNextEventTime ( &ct );

    if ( f )
    {
        // calculate delta time from last event time
        double delta_clocks = ( double ) ( ct - state.cur_clock );
        // calculate tempo in milliseconds per clock
        double clocks_per_sec = ( ( state.track_state[0]->tempobpm *
                                    ( ( ( double ) tempo_scale ) * 0.01 )
                                    * ( 1. / 60. ) ) * state.multitrack->GetClksPerBeat() );

        if ( clocks_per_sec > 0. )
        {
            double ms_per_clock = 1000. / clocks_per_sec;
            // calculate delta time in milliseconds
            double delta_ms = delta_clocks * ms_per_clock;
            // return it added with the current time in ms.
            *t = delta_ms + state.cur_time_ms;
        }

        else
        {
            f = false;
        }
    }

    return f;
}
bool MIDISequencer::GoToTime ( MIDIClockTime time_clk )
{
    // temporarily disable the gui notifier
    bool notifier_mode = false;

    if ( state.notifier )
    {
        notifier_mode = state.notifier->GetEnable();
        state.notifier->SetEnable ( false );
    }

    if ( time_clk < state.cur_clock || time_clk == 0 )
    {
        // start from zero if desired time is before where we are
        for ( int i = 0; i < state.num_tracks; ++i )
        {
            state.track_state[i]->GoToZero();
        }

        state.iterator.GoToTime ( 0 );
        state.cur_time_ms = 0.0;
        state.cur_clock = 0;
//  state.next_beat_time = state.multitrack->GetClksPerBeat();
        state.next_beat_time =
            state.multitrack->GetClksPerBeat()
            * 4 / ( state.track_state[0]->timesig_denominator );
        state.cur_beat = 0;
        state.cur_measure = 0;
    }

    MIDIClockTime t = 0;
    int trk;
    MIDITimedBigMessage ev;

    while (
        GetNextEventTime ( &t )
        && t < time_clk
        && GetNextEvent ( &trk, &ev )
    )
    {
        ;
    }

    // examine all the events at this specific time
    // and update the track states to reflect this time
    ScanEventsAtThisTime();

    // re-enable the gui notifier if it was enabled previously
    if ( state.notifier )
    {
        state.notifier->SetEnable ( notifier_mode );
        // cause a full gui refresh now
        state.notifier->Notify ( this, MIDISequencerGUIEvent::GROUP_ALL );
    }

    return true;
}
Exemplo n.º 4
0
  bool MIDISequencer::GoToMeasure( int measure, int beat ) 
  {
    // temporarily disable the gui notifier
    
    bool notifier_mode=false;
    if( state.notifier )
    {
      notifier_mode = state.notifier->GetEnable();
      state.notifier->SetEnable(false);
    }
    
    if( measure < state.cur_measure || measure==0 )
    {
      for( int i=0; i<state.num_tracks; ++i )
      {
        state.track_state[i]->GoToZero();
      }
      
      state.iterator.GoToTime( 0 );
      
      state.cur_time_ms = 0.0;
      state.cur_clock = 0;
      state.cur_beat = 0;
      state.cur_measure = 0;
//		state.next_beat_time = state.multitrack->GetClksPerBeat();
      state.next_beat_time =
        state.multitrack->GetClksPerBeat()
        * 4 / (state.track_state[0]->timesig_denominator);
      
    }
    
    MIDIClockTime t=0;
    int trk;
    MIDITimedBigMessage ev;
    
    // iterate thru all the events until cur-measure and cur_beat are
    // where we want them.
    
    while(
      GetNextEventTime( &t )
      && GetNextEvent(&trk,&ev)
      && state.cur_measure<=measure
      )
    {
      if( state.cur_measure==measure && state.cur_beat>=beat )
      {
        break;
      }
    }
    
    
    // examine all the events at this specific time
    // and update the track states to reflect this time
    
    
    ScanEventsAtThisTime();
    
    
    
    // re-enable the gui notifier if it was enabled previously
    if( state.notifier )
    {
      state.notifier->SetEnable( notifier_mode );
      
      // cause a full gui refresh now
      
      state.notifier->Notify( this, MIDISequencerGUIEvent::GROUP_ALL );
    }
    
    // return true if we actually found the measure requested
    
    return state.cur_measure == measure && state.cur_beat == beat;
    
  } 
Exemplo n.º 5
0
 bool MIDISequencer::GetNextEvent( int *tracknum, MIDITimedBigMessage *msg ) 
 {
   MIDIClockTime t;
   
   
   // ask the iterator for the current event time
   if( state.iterator.GetCurEventTime(&t) )
   {
     // move current time forward one event
     
     MIDIClockTime new_clock;
     float new_time_ms=0.0f;
     
     GetNextEventTime( &new_clock );
     GetNextEventTimeMs( &new_time_ms );
     
     // must set cur_clock AFTER GetnextEventTimeMs() is called
     // since GetNextEventTimeMs() uses cur_clock to calculate
     
     state.cur_clock = new_clock;
     state.cur_time_ms = new_time_ms;
     
     
     // is the next beat marker before this event?
     
     if( state.next_beat_time<=t )
     {
       // yes, this is a beat event now.
       
       // say this event came on track 0, the conductor track
       *tracknum = 0;
       
       // put current info into beat marker message
       beat_marker_msg.SetBeatMarker();
       beat_marker_msg.SetTime( state.next_beat_time );
       *msg = beat_marker_msg;
       
       // update our beat count
       
       int new_beat = state.cur_beat+1;
       int new_measure = state.cur_measure;
       
       // do we need to update the measure number?
       
       if( new_beat>=state.track_state[0]->timesig_numerator )
       {
         // yup
         
         new_beat=0;
         ++new_measure;
       }
       
       // update our next beat time
       
       
       // denom=4  (16) ---> 4/16 midi file beats per symbolic beat
       // denom=3  (8)  ---> 4/8 midi file beats per symbolic beat
       // denom=2  (4)  ---> 4/4 midi file beat per symbolic beat
       // denom=1  (2)  ---> 4/2 midi file beats per symbolic beat
       // denom=0  (1)  ---> 4/1 midi file beats per symbolic beat
       
       state.next_beat_time +=
         state.multitrack->GetClksPerBeat()
         * 4 / (state.track_state[0]->timesig_denominator);
       
       state.cur_beat = new_beat;
       state.cur_measure = new_measure;
       
       // now notify the GUI that the beat number changed
       state.notifier->Notify(
         this,
         MIDISequencerGUIEvent(
           MIDISequencerGUIEvent::GROUP_TRANSPORT,
           0,
           MIDISequencerGUIEvent::GROUP_TRANSPORT_BEAT
           )
         );
       
       // if the new beat number is 0 then the measure changed too
       if( state.cur_beat==0 )
       {
         state.notifier->Notify(
           this,
           MIDISequencerGUIEvent(
             MIDISequencerGUIEvent::GROUP_TRANSPORT,
             0,
             MIDISequencerGUIEvent::GROUP_TRANSPORT_MEASURE
             )
           );
       }
       
       // give the beat marker event to the conductor track to process
       state.track_state[*tracknum]->Process(msg);
       
       
       return true;
     }
     else	// this event comes before the next beat
     {
       MIDITimedBigMessage *msg_ptr;
       
       if( state.iterator.GetCurEvent( tracknum, &msg_ptr ) )
       {
         int trk=*tracknum;
         
         // copy the event so Process can modify it
         
         *msg = *msg_ptr;
         
         bool allow_msg=true;
         
         // are we in solo mode?
         
         if( solo_mode )
         {
           // yes, only allow this message thru if
           // the track is either track 0
           // or it is explicitly solod.
           
           if( trk==0 || track_processors[trk]->solo )
           {
             allow_msg=true;
           }
           else
           {
             allow_msg=false;
           }
           
         }
         
         
         if( !(allow_msg
               && track_processors[trk]->Process(msg)
               && state.track_state[trk]->Process(msg))
           )
         {
           // the message is not allowed to come out!
           // erase it
           msg->SetNoOp();
         }
         
         // go to the next event on the multitrack
         state.iterator.GoToNextEvent();
         
         return true;
         
       }
     }
   }
   
   return false;
 }