使用 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,
×tamp,
&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,
×tamp,
&eventType,
&eventData,
&eventDataSize);
if (eventType == kMusicEventType_ExtendedTempo &&
eventDataSize == sizeof(ExtendedTempoEvent)) {
ExtendedTempoEvent *tempoEvent = (ExtendedTempoEvent *)eventData;
Float64 tempo = tempoEvent->bpm;
NSLog(@"Tempo is %g", tempo);
}
请记住:一个 MIDI 文件中可能有不止一种速度。您可以使用事件时间戳来了解它何时改变速度。
我想知道如何使用 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,
×tamp,
&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,
×tamp,
&eventType,
&eventData,
&eventDataSize);
if (eventType == kMusicEventType_ExtendedTempo &&
eventDataSize == sizeof(ExtendedTempoEvent)) {
ExtendedTempoEvent *tempoEvent = (ExtendedTempoEvent *)eventData;
Float64 tempo = tempoEvent->bpm;
NSLog(@"Tempo is %g", tempo);
}
请记住:一个 MIDI 文件中可能有不止一种速度。您可以使用事件时间戳来了解它何时改变速度。