合成器延迟

合成器计时的另一个考虑因素是延迟,即当前时间和音符第一次播放时间之间的差异。 MIDI 消息无法在当前采样时间提交到合成器并呈现到输出缓冲区。 对于已经放置在缓冲器中但尚未流式传输到波形输出设备的数据,应留出余量。

因此,波接收器应实现延迟时钟,即 IReferenceClock 对象(Microsoft Windows SDK 文档中所述)。 延迟时钟的 IReferenceClock::GetTime 方法检索数据已写入缓冲区的采样时间,并将其转换为相对于主时钟的参考时间。 波形接收器使用 IDirectMusicSynthSink::SampleToRefTimeIDirectMusicSynthSink::RefTimeToSample 在参考时间和采样时间之间进行转换,因此在这种情况下,合成器调用 IDirectMusicSynthSink::RefTimeToSample 来完成转换。

延迟时间全部由波形接收器管理。 IDirectMusicSynthSink::GetLatencyClock 方法的实现应输出指向延迟时钟的指针,并且此指针必须由 IDirectMusicSynth::GetLatencyClock 检索。 应用程序通过调用 IDirectMusicSynth::PlayBuffer 方法,使用延迟时钟来确定 MIDI 消息传递到合成器时可以排队播放的最早时间点。

MIDI 消息的延迟示例如下图所示。

Diagram illustrating the latency of a MIDI message in a PCM buffer loop.

在上图中,延迟时钟指向 PCM 缓冲区循环中可以播放音符的第一个位置。 请注意,主时钟以 22 个时间单位为单位,这是当前播放声音的点,但 22 到 30 个时间单位之间的空间已经被波形数据填满,无法再写入。 因此,可以安排播放新的带时间戳的 MIDI 事件的第一个地方是时间 30。 因此,延迟时钟读取 30 个时间单位。

消息可以安排在这个延迟时间播放,也可以安排在该延迟时间之后的任何时间播放。 因此,要立即呈现的消息在被放入合成器的输入缓冲区之前,会被标记上延迟时间(而不是当前时间)。