02fentym
02fentym

Reputation: 1792

Tempo of MIDI File Using CoreMidi

I was wondering how to find the tempo of a midi file using the CoreMidi framework. As I understand it, the MusicSequence class is used for opening a midi file. It contains a number of tracks including a tempo track which is of type MusicTrack. Upon inspecting the MusicTrack class, there doesn't seem to be any parameter or method for actually getting the tempo. I got the following code from this site...here's the code:

-(void) openMidiFile {
    MusicSequence sequence;
    NewMusicSequence(&sequence);

    NSURL *midiFileURL = [[NSBundle mainBundle] URLForResource:@"bach-invention-01" withExtension:@"mid"];

    MusicSequenceFileLoad(sequence, (__bridge CFURLRef)midiFileURL, 0,
                      kMusicSequenceLoadSMF_ChannelsToTracks); //needs to change later

    MusicTrack tempoTrack;
    MusicSequenceGetTempoTrack(sequence, &tempoTrack);

    MusicEventIterator iterator;
    NewMusicEventIterator(tempoTrack, &iterator);

    Boolean hasNext = YES;
    MusicTimeStamp timestamp = 0;
    MusicEventType eventType = 0;
    const void *eventData = NULL;
    UInt32 eventDataSize = 0;

    // Run the loop
    MusicEventIteratorHasCurrentEvent(iterator, &hasNext);
    while (hasNext) {
        MusicEventIteratorGetEventInfo(iterator,
                                   &timestamp,
                                   &eventType,
                                   &eventData,
                                   &eventDataSize);

        // Process each event here
        printf("Event found! type: %d\n", eventType); //tempo occurs when eventType is 3
        printf("Event data: %d\n", (int)eventData); //data for tempo?

        MusicEventIteratorNextEvent(iterator);
        MusicEventIteratorHasCurrentEvent(iterator, &hasNext);
    }
}

Upvotes: 1

Views: 382

Answers (1)

Kurt Revis
Kurt Revis

Reputation: 27994

Each eventType has a corresponding structure for its data, described in MusicPlayer.h.

You are probably looking for events of type kMusicEventType_ExtendedTempo, which will have data of type ExtendedTempoEvent, which is just:

/*!
    @struct     ExtendedTempoEvent
    @discussion specifies the value for a tempo in beats per minute
*/
typedef struct ExtendedTempoEvent
{
    Float64     bpm;
} ExtendedTempoEvent;

So your code might be:

MusicEventIteratorGetEventInfo(iterator,
                               &timestamp,
                               &eventType,
                               &eventData,
                               &eventDataSize);

if (eventType == kMusicEventType_ExtendedTempo && 
    eventDataSize == sizeof(ExtendedTempoEvent)) {
    ExtendedTempoEvent *tempoEvent = (ExtendedTempoEvent *)eventData;
    Float64 tempo = tempoEvent->bpm;
    NSLog(@"Tempo is %g", tempo);
}

Keep in mind: a MIDI file may have more than one tempo in it. You can use the event timestamps to find out when it changes tempo.

Upvotes: 1

Related Questions