コード例 #1
0
void CollapseMultiTrack( const MIDIMultiTrack &src, MIDIMultiTrack &dst )
{
    dst.ClearAndResize( 1 );
    dst.SetClksPerBeat( src.GetClksPerBeat() );

    MIDISequencer seq( &src );
    seq.GoToZero();

    MIDITimedBigMessage ev;
    int ev_track;
    while ( seq.GetNextEvent( &ev_track, &ev ) )
    {
        // ignore all src EndOfTrack messages!!
        if ( ev.IsDataEnd() )
            continue;

        // ignore NoOp, BeatMarker and other Service messages
        if ( ev.IsServiceMsg() || ev.IsNoOp() )
            continue;

        dst.GetTrack(0)->PutEvent(ev);
    }

    // set (single!) dst EndOfTrack message
    MIDITimedBigMessage end(ev); // copy time of last src event
    end.SetDataEnd();
    dst.GetTrack(0)->PutEvent(end);
}
コード例 #2
0
void CopyWithoutChannel( const MIDIMultiTrack &src, MIDIMultiTrack &dst, int ignore_channel )
{
    dst.ClearAndResize( src.GetNumTracks() );
    dst.SetClksPerBeat( src.GetClksPerBeat() );

    MIDIClockTime ev_time = 0;
    MIDISequencer seq( &src );
    seq.GoToTime( 0 );
    if ( !seq.GetNextEventTime ( &ev_time ) )
        return; // empty src multitrack

    MIDITimedBigMessage ev;
    int ev_track;

    while ( seq.GetNextEvent( &ev_track, &ev ) )
    {
        if ( ev.IsServiceMsg() || ev.IsNoOp() )
            continue;

        if ( ev.IsChannelEvent() && ev.GetChannel() == ignore_channel )
            continue;

        dst.GetTrack(ev_track)->PutEvent(ev);
    }
}
コード例 #3
0
void ClipMultiTrack( const MIDIMultiTrack &src, MIDIMultiTrack &dst, double max_time_sec )
{
    dst.ClearAndResize( src.GetNumTracks() );
    dst.SetClksPerBeat( src.GetClksPerBeat() );

    double max_event_time = 1000.*max_time_sec; // msec
    double event_time = 0.; // msec

    MIDISequencer seq( &src );
    seq.GoToTimeMs( 0.f );
    if ( !seq.GetNextEventTimeMs ( &event_time ) )
        return; // empty src multitrack

    MIDITimedBigMessage ev;
    int ev_track;
    while ( seq.GetNextEvent( &ev_track, &ev ) )
    {
        // ignore NoOp, BeatMarker and other Service messages
        if ( ev.IsServiceMsg() || ev.IsNoOp() )
            continue;

        dst.GetTrack(ev_track)->PutEvent(ev);

        if ( event_time >= max_event_time )
            break; // end of max_time_sec

        if ( !seq.GetNextEventTimeMs( &event_time ) )
            break; // end of src multitrack
    }
}
コード例 #4
0
ファイル: GenePool.cpp プロジェクト: mishan/quickhacks
GenePool::MIDIEventList *GenePool::getEvents(void)
{
	list<MIDITimedBigMessage*> *events = new list<MIDITimedBigMessage*>;

    for (EventPool::iterator i = pool_.begin(); i != pool_.end(); ++i)
    {
		for (BreadNoteCluster::iterator j = (*i)->begin(); j != (*i)->end(); ++j)
		{
            BreadNote *e = (*j);
			
            u_int8_t pitch = e->pitch();
            u_int32_t ontime = e->ontime();
            u_int32_t duration = e->duration();
            u_int8_t channel = e->channel();
            u_int8_t dynamic = e->dynamic();

			MIDITimedBigMessage *m = new MIDITimedBigMessage;
			m->SetTime(ontime);
			m->SetNoteOn(channel, pitch, dynamic);
			events->push_back(m);
			m = new MIDITimedBigMessage;
			m->SetTime(ontime+duration);
			m->SetNoteOff(channel, pitch, dynamic);
			events->push_back(m);

//            printf("(%d %d %d %d %d) ", ontime, pitch, duration, channel,
//                   dynamic);
        }
	}

	return events;
}
コード例 #5
0
int AdvancedSequencer::FindFirstChannelOnTrack ( int trk )
{
    if ( !file_loaded )
    {
        return -1;
    }

    int first_channel = -1;
    MIDITrack *t = tracks.GetTrack ( trk );

    if ( t )
    {
        // go through all events
        // until we find a channel message
        // and then return the channel number plus 1
        for ( int i = 0; i < t->GetNumEvents(); ++i )
        {
            MIDITimedBigMessage *m = t->GetEventAddress ( i );

            if ( m )
            {
                if ( m->IsChannelMsg() )
                {
                    first_channel = m->GetChannel() + 1;
                    break;
                }
            }
        }
    }

    return first_channel;
}
コード例 #6
0
bool AddEndingPause( MIDIMultiTrack &tracks, int track_num, MIDIClockTime pause_ticks )
{
    MIDIClockTime t = tracks.GetTrack( track_num )->GetLastEventTime();
    MIDITimedBigMessage msg;
    msg.SetTime( t + pause_ticks );
    // add lowest "note on" in channel 0 with velocity 0 (i.e. "note off")
    msg.SetNoteOn( 0, 0, 0 );
    return tracks.GetTrack( track_num )->PutEvent( msg );
}
コード例 #7
0
std::string EventAsText(const MIDITimedBigMessage &ev)
{
    char buf[256];
    ev.MsgToText( buf );
    MIDIClockTime time = ev.GetTime();

    /*std::ostringstream ostr;
    ostr << " Midi tick " << time;
    ostr << "  MSG " << buf << " ";
    return ostr.str();*/
	  return std::string("EventAsText Stub");
}
コード例 #8
0
 bool MIDIDriverDump::HardwareMsgOut ( const MIDITimedBigMessage &msg )
 {
   char buf[256];
   
   fprintf ( f, "OUTPUT: %s\n", msg.MsgToText ( buf ) );
   return true;
 }
コード例 #9
0
 bool	MIDITrack::PutEvent( const MIDITimedMessage &msg, MIDISystemExclusive *sysex )	
 {
   if( num_events >= buf_size )
   {
     if( !Expand() )
       return false;
   }
   
   MIDITimedBigMessage *e = GetEventAddress( num_events );
   
   e->Copy( msg );
   e->CopySysEx( sysex );
   
   ++num_events;
   
   return true;
 } 
コード例 #10
0
 bool	MIDITrack::MakeEventNoOp( int event_num ) 
 {
   if( event_num>=num_events )
   {
     return false;
   }
   else
   {
     MIDITimedBigMessage *ev = GetEventAddress( event_num );
     
     if( ev )
     {
       ev->ClearSysEx();
       ev->SetNoOp();
     }
     return true;
   }
 } 
コード例 #11
0
void LastEventsProlongation( MIDIMultiTrack &tracks, int track_num, MIDIClockTime add_ticks )
{
    MIDITrack *track = tracks.GetTrack( track_num );
    int index = track->GetNumEvents() - 1;
    if ( add_ticks == 0 || index < 0 )
        return;

    MIDITimedBigMessage *msg = track->GetEvent( index );
    MIDIClockTime tmax = msg->GetTime();

    while ( msg->GetTime() == tmax )
    {
        msg->SetTime( tmax + add_ticks );
        if ( --index < 0 )
            break;
        msg = track->GetEvent( index );
    }
}
コード例 #12
0
void CompressStartPause( const MIDIMultiTrack &src, MIDIMultiTrack &dst, int ignore_channel )
{
    dst.ClearAndResize( src.GetNumTracks() );
    dst.SetClksPerBeat( src.GetClksPerBeat() );

    MIDIClockTime ev_time = 0;
    MIDISequencer seq( &src );
    seq.GoToTime( 0 );
    if ( !seq.GetNextEventTime ( &ev_time ) )
        return; // empty src multitrack

    MIDITimedBigMessage ev;
    int ev_track;
    bool compress = true;
    MIDIClockTime old_ev_time = 0, delta_ev_time = 0, ev_time0 = 0;

    while ( seq.GetNextEvent( &ev_track, &ev ) )
    {
        if ( ev.IsServiceMsg() || ev.IsNoOp() )
            continue;

        if ( ev.IsChannelEvent() && ev.GetChannel() == ignore_channel )
            continue;

        ev_time = ev.GetTime();
        if ( compress )
        {
            // compress time intervals between adjacent messages to 1 tick
            if (ev_time > old_ev_time)
                ++delta_ev_time;

            old_ev_time = ev_time;

            ev.SetTime( delta_ev_time );

            if ( ev.ImplicitIsNoteOn() )
            {
                compress = false;
                ev_time0 = ev_time - delta_ev_time;
            }
        }
        else
        {
            ev.SetTime( ev_time - ev_time0 );
        }

        dst.GetTrack(ev_track)->PutEvent(ev);
    }
}
コード例 #13
0
 bool MIDIMultiTrackIterator::GoToNextEventOnTrack ( int track_num )
 {
   // Get the track that we are dealing with
   MIDITrack *track = multitrack->GetTrack ( track_num );
   
   // Get ptr to the current event number for this track
   int *event_num = &state.next_event_number[ track_num ];
   
   // skip this track if this event number is <0 - This track has hit end already.
   
   if ( *event_num <0 )
   {
     return false; // at end of track
   }
   
   // increment *event_num to next event on track
   
   ( *event_num ) += 1;
   
   // are we at end of track?
   if ( *event_num >= track->GetNumEvents() )
   {
     // yes, set *event_num to -1
     *event_num=-1;
     return false; // at end of track
   }
   else
   {
     // not at end of track yet - get the time of the event
     MIDITimedBigMessage *msg;
     
     msg = track->GetEventAddress ( *event_num );
     
     state.next_event_time[ track_num ] = msg->GetTime();
   }
   
   
   
   return true;
 }
コード例 #14
0
double MIDISequencer::GetMusicDurationInSeconds()
{
    double event_time = 0.; // in milliseconds

    MIDITimedBigMessage ev;
    int ev_track;

    GoToZero();

    while ( GetNextEvent( &ev_track, &ev ) )
    {
        // std::cout << "MIDISequencer::GetMusicDurationInSeconds: " << EventAsText( ev ) << std::endl;

        // skip these events
        if ( ev.IsEndOfTrack() || ev.IsBeatMarker() )
            continue;

        // end of music is the time of last not end of track midi event!
        event_time = GetCurrentTimeInMs();
    }

    return ( 0.001 * event_time );
}
コード例 #15
0
// delete all text events from multitrack object
bool DeleteAllTracksText( MIDIMultiTrack &tracks )
{
    bool text_deleted = false;
    int num_tracks = tracks.GetNumTracksWithEvents();

    for ( int nt = 0; nt < num_tracks; ++nt )
    {
        MIDITrack &trk = *tracks.GetTrack( nt );
        int num_events = trk.GetNumEvents();

        for ( int ne = 0; ne < num_events; ++ne )
        {
            MIDITimedBigMessage *msg = trk.GetEvent( ne );
            // convert any text midi event to NoOp event
            if ( msg->IsTextEvent() )
            {
                trk.MakeEventNoOp( ne );
                text_deleted = true;
            }
        }
    }

    return text_deleted;
}
コード例 #16
0
void MIDIDriver::AllNotesOff ( int chan )
{
    MIDITimedBigMessage msg;
    // send a note off for every note on in the out_matrix

    if ( out_matrix.GetChannelCount ( chan ) > 0 )
    {
        for ( int note = 0; note < 128; ++note )
        {
            while ( out_matrix.GetNoteCount ( chan, note ) > 0 )
            {
                // make a note off with note on msg, velocity 0
                msg.SetNoteOn ( ( unsigned char ) chan,
                                ( unsigned char ) note, 0 );
                OutputMessage ( msg );
            }
        }
    }

    msg.SetControlChange ( chan, C_DAMPER, 0 );
    OutputMessage ( msg );
    msg.SetAllNotesOff ( ( unsigned char ) chan );
    OutputMessage ( msg );
}
コード例 #17
0
void AdvancedSequencer::ExtractMarkers ( std::vector< std::string > *list )
{
    if ( !file_loaded )
    {
        list->clear();
        num_markers = 0;
        return;
    }

    MIDITrack *t = tracks.GetTrack ( 0 );
    list->clear();
    int cnt = 0;
    int measure = 0;
    int beat = 0;
    int timesig_numerator = 4;
    int timesig_denominator = 4;
    MIDIClockTime last_beat_time = 0;
    MIDIClockTime last_event_time = 0;
    int clks_per_beat = tracks.GetClksPerBeat();

    for ( int i = 0; i < t->GetNumEvents(); ++i )
    {
        MIDITimedBigMessage *m = t->GetEventAddress ( i );

        if ( m )
        {
            // how many beats have gone by since the last event?
            long beats_gone_by = ( m->GetTime() - last_beat_time ) / clks_per_beat;

            if ( beats_gone_by > 0 )
            {
                // calculate what our new measure/beat is
                beat += beats_gone_by;
                // carry over beat overflow to measure
                measure += beat / timesig_numerator;
                beat = beat % timesig_numerator;
                last_beat_time += ( clks_per_beat * beats_gone_by );
            }

            if ( m->IsMetaEvent() && m->IsTimeSig() )
            {
                timesig_numerator = m->GetTimeSigNumerator();
                timesig_denominator = m->GetTimeSigDenominator();
                clks_per_beat = tracks.GetClksPerBeat() * 4 / timesig_denominator;
            }

            if ( m->IsTextEvent() && m->GetSysEx() )
            {
                if ( ( m->GetMetaType() == META_GENERIC_TEXT )
                        || m->GetMetaType() == META_MARKER_TEXT
                        || m->GetMetaType() == META_CUE_TEXT )
                {
                    char buf[256];
                    char line[256];
                    memcpy ( buf, m->GetSysEx()->GetBuf(), m->GetSysEx()->GetLength() );
                    buf[ m->GetSysEx()->GetLength() ] = '\0';
                    FixQuotes ( buf );
                    sprintf ( line, "%03d:%d        %s", measure + 1, beat + 1, buf );
                    list->push_back ( std::string ( line ) );
                    marker_times[ cnt++ ] = m->GetTime();
                }
            }

            last_event_time = m->GetTime();
        }
    }

    num_markers = cnt;
}
コード例 #18
0
 void MIDIMultiTrackIterator::GoToTime ( MIDIClockTime time )
 {
   // start at time 0
   
   state.Reset();
   
   // transfer info from the first events in each track in the
   // multitrack object to our current state.
   
   for ( int i=0; i<multitrack->GetNumTracks(); ++i )
   {
     MIDITrack *track = multitrack->GetTrack ( i );
     
     // default: set the next_event_number for this track to -1
     // to signify end of track
     
     state.next_event_number[ i ] = -1;
     
     // are there any events in this track?
     if ( track && track->GetNumEvents() >0 )
     {
       // yes, extract the time of the first event
       
       MIDITimedBigMessage *msg = track->GetEventAddress ( 0 );
       
       if ( msg )
       {
         // found the first message of the track. Keep track
         // of the event number and the event time.
         
         state.next_event_number[i]=0;
         state.next_event_time[i]=msg->GetTime();
       }
     }
   }
   
   
   // are there any events at all? find the track with the
   // earliest event
   
   if ( state.FindTrackOfFirstEvent() !=-1 )
   {
     // yes
     // iterate through all the events until we find a time >= the requested time
     
     while ( state.GetCurrentTime() <time )
     {
       // did not get to the requested time yet.
       // go to the next chronological event on all tracks
       
       if ( !GoToNextEvent() )
       {
         // there is no more events to go to
         
         break;
       }
       
     }
   }
   
 }
コード例 #19
0
 void	MIDITrack::ClearAndMerge(
   const MIDITrack *src1,
   const MIDITrack *src2
   )
 {
   Clear();
   
   const MIDITimedBigMessage *ev1;
   int cur_trk1ev=0;
   int num_trk1ev = src1->GetNumEvents();
   
   const MIDITimedBigMessage *ev2;
   int cur_trk2ev=0;
   int num_trk2ev = src2->GetNumEvents();
   
   MIDIClockTime last_data_end_time=0;
   
   while(
     cur_trk1ev<num_trk1ev
     || cur_trk2ev<num_trk2ev
     )
   {
     // skip any NOPs on track 1
     
     ev1=src1->GetEventAddress( cur_trk1ev );
     ev2=src2->GetEventAddress( cur_trk2ev );
     
     bool has_ev1 = (cur_trk1ev<num_trk1ev) && ev1;
     bool has_ev2 = (cur_trk2ev<num_trk2ev) && ev2;
     
     if( has_ev1 && ev1->IsNoOp() )
     {
       cur_trk1ev++;
       continue;
     }
     
     // skip any NOPs on track 2
     
     if( has_ev2 && ev2->IsNoOp() )
     {
       cur_trk2ev++;
       continue;
     }
     
     // skip all data end
     
     if( has_ev1 && ev1->IsDataEnd() )
     {
       if( ev1->GetTime() > last_data_end_time )
       {
         last_data_end_time = ev1->GetTime();
       }
       cur_trk1ev++;
       continue;
     }
     
     if( has_ev2 && ev2->IsDataEnd() )
     {
       if( ev2->GetTime() > last_data_end_time )
       {
         last_data_end_time = ev2->GetTime();
       }
       cur_trk2ev++;
       continue;
     }
     
     if( (has_ev1 && !has_ev2) )
     {
       // nothing left on trk 2
       
       if( !ev1->IsNoOp())
       {
         if( ev1->GetTime() > last_data_end_time )
         {
           last_data_end_time = ev1->GetTime();
         }
         
         PutEvent( *ev1 );
         ++cur_trk1ev;
       }
     } else if( (!has_ev1 && has_ev2) )
     {
       // nothing left on trk 1
       if( !ev2->IsNoOp() )
       {
         PutEvent( *ev2 );
         ++cur_trk2ev;
       }
     } else if( has_ev1 && has_ev2 )
     {
       int trk=1;
       
       if( (ev1->GetTime() <= ev2->GetTime()) )
       {
         trk=1;
       }
       else
       {
         trk=2;
       }
       
       if( trk==1 )
       {
         if( ev1->GetTime() > last_data_end_time )
         {
           last_data_end_time = ev1->GetTime();
         }
         
         PutEvent( *ev1 );
         
         ++cur_trk1ev;
       }
       else
       {
         if( ev2->GetTime() > last_data_end_time )
         {
           last_data_end_time = ev2->GetTime();
         }
         
         PutEvent( *ev2 );
         ++cur_trk2ev;
       }
     }
   }
   
   // put single final data end event
   
   MIDITimedBigMessage dataend;
   
   dataend.SetTime( last_data_end_time );
   dataend.SetDataEnd();
   
   PutEvent( dataend );
 }
コード例 #20
0
void SoloMelodyConverter( const MIDIMultiTrack &src, MIDIMultiTrack &dst, int ignore_channel )
{
    // this simple code works better for src MultiTrack with 1 track,
    // if not, we can make before the call of CollapseMultiTrack()

    dst.ClearAndResize( src.GetNumTracks() );
    dst.SetClksPerBeat( src.GetClksPerBeat() );

    MIDIClockTime ev_time = 0;
    MIDISequencer seq( &src );
    seq.GoToTime( 0 );
    if ( !seq.GetNextEventTime ( &ev_time ) )
        return; // empty src multitrack

    MIDITimedBigMessage ev;
    int ev_track;

    int solo_note = -1; // highest midi note number in current time, valid values 0...127
    bool solo_note_on = false;
    MIDITimedBigMessage solo_note_on_ev; // last solo note on event
    solo_note_on_ev.SetNoOp();

    while ( seq.GetNextEvent( &ev_track, &ev ) )
    {
        if ( ev.IsServiceMsg() || ev.IsNoOp() )
            continue;

        if ( ev.IsChannelEvent() )
        {
            if ( ev.GetChannel() == ignore_channel )
                continue;

//          if ( ev.IsAllNotesOff() ) ... ; // for future work...

            if ( ev.IsNote() )
            {
                int new_note = ev.GetNote();

                // skip all note events if new note lower than solo note
                if ( new_note < solo_note )
                    continue;
                // else ( new_note >= solo_note )

                if ( ev.ImplicitIsNoteOn() ) // new note on event
                {
                    if ( solo_note_on ) // new note on after previous solo note on
                    {
                        // make noteoff message for previous solo note
                        solo_note_on_ev.SetTime( ev.GetTime() );
                        solo_note_on_ev.SetVelocity( 0 ); // note off
                        dst.GetTrack(ev_track)->PutEvent( solo_note_on_ev );

                        // make new solo note
                        solo_note_on_ev = ev;
                        solo_note = new_note;
                    }
                    else // ( solo_note_on == false ) - new note on after previous silence
                    {
                        // make new solo note
                        solo_note_on = true;
                        solo_note_on_ev = ev;
                        solo_note = new_note;
                    }
                }
                else // new note off event ( new_note >= solo_note )
                {
                    if ( solo_note_on ) // new note off after previous solo note on
                    {
                        if ( new_note == solo_note ) // solo note off event
                        {
                            // test channels of the events
                            if ( ev.GetChannel() == solo_note_on_ev.GetChannel() )
                            {
                                solo_note_on = false;
                                solo_note = -1; // erase solo_note
                            }
                            else
                                continue; // skip other note off stuff
                        }
                        else // ( new_note > solo_note ) any other note off event
                            continue; // skip other note off stuff
                    }
                    else // ( solo_note_on == false ) - new note off after previous silence
                        continue; // skip other note off stuff
                }
            }
        }
        dst.GetTrack(ev_track)->PutEvent(ev);
    }
}