使用 CoreMidi 的 MIDI 文件速度

Tempo of MIDI File Using CoreMidi

我想知道如何使用 CoreMidi 框架找到 midi 文件的速度。据我了解,MusicSequence class 用于打开 midi 文件。它包含许多曲目,包括 MusicTrack 类型的速度曲目。检查 MusicTrack class 后,似乎没有任何参数或方法可以实际获取速度。我从这个 site 得到了以下代码...这是代码:

-(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);
    }
}

每个 eventType 都有对应的数据结构,如 MusicPlayer.h 所述。

您可能正在查找 kMusicEventType_ExtendedTempo 类型的事件,其中包含 ExtendedTempoEvent 类型的数据,即:

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

因此您的代码可能是:

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);
}

请记住:一个 MIDI 文件中可能有不止一种速度。您可以使用事件时间戳来了解它何时改变速度。