CoreMIDI:坚如磐石的midi同步

时间:2012-03-16 15:08:07

标签: objective-c c coremidi

我在midi同步方面遇到了麻烦。在syntheticbits.com上的帖子之后,我使用了一个PGMidi类。 同步有效,但不断变为1-2 bpm。

以下是我使用的代码:

- (void)sendMidiClockInMidiThread {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [lock lock];

    const int64_t kOneMillion = 1000 * 1000;
    const UInt8   tick[]      = { 0xF8 };

    // Calculate tick time
    // returns sample for sixteen note (5512 if current bpm is 120)
    SInt32 sixteen     = AGGetSamples_SixteensWithoutSwing(_grid, 1.0);
    UInt64 tickTime    = (sixteen / 6) * kOneMillion;
    int    tickLatency = 0;
    // Send ticks messages
    for (int i = 0; i < 6; ++i) {
         int beginTime = clock();
         hostTime      = hostTime + (tickTime - tickLatency);
         [self.midi sendBytes:tick size:sizeof(tick) atTime:hostTime];
         int endTime   = clock();
         tickLatency   = endTime - beginTime;
    }

    [lock unlock];
    [pool drain];
}

请告诉我如何明确同步。

1 个答案:

答案 0 :(得分:0)

首先:这个消息从何处被调用?你的计时器是什么?您需要确保使用非常准确的计时器。你基本上需要一些比10ms更紧的东西(20ms是MIDI时钟脉冲的周期,每四分音符24个脉冲,每分钟120个四分音符)。

This guy对iOS / MacOS上提供的同步原语进行了相当不错的写作。

他在这里的最坏情况(涉及自旋锁定)在最坏的情况下仍然偏差近50ms,在平均情况下偏差14ms。对于MIDI来说这绝对是一个糟糕的时机。最好的办法是使用可用的信息here启动CoreAudio线程(或实时线程)。