我在写C ++代码起着两个数字音频(合成音乐)和MIDI音乐在同一时间(使用RtMidi库)。数字化的音乐将发挥出电脑的音频设备,但是MIDI音乐可以打出来的外部合成器。 我想玩同时使用数字化仪器和MIDI乐器一首歌,我不知道的这两个音频流进行同步的最佳方式:
- 这是不可能使用像睡眠功能()作为延迟时间是既不平衡,太长我的需求(这是一毫秒的量级上。)当被要求只为1ms为5毫秒如果睡眠()定期等待,所产生的乐曲的速度将被关闭,除非它的确切每次叫时,速度将是不平衡的。
- 计数放入音频缓冲器的样本的数目提供了用于数字音频音符之间的超精确的定时(一个样品的最小延迟 - 在48kHz的0.02ms),但该定时不能被用于MIDI。 因为音频被缓冲的音符以突发(一次填充一个音频缓冲器,尽可能快地)合成,从而这导致一堆MIDI音符被与每一个数字音频缓冲器需要时间它们之间没有延迟播放回填。
- 现场演奏MIDI数据没有定时信息,因此一张纸条,只要它被送到播放。 因此,一个音符无法安排在稍后的时间玩,所以我需要在正确的时间正确地发送MIDI事件自己。
目前我使用了nanosleep() - 这仅适用于Linux,而不是Windows下工作 - 等待音符之间正确的时间。 这允许数字音频和MIDI数据保持同步,但是了nanosleep(),因此所得到的速度是非常不均匀的不是非常一致。
任何人都可以想办法保留两个数字音频和MIDI数据音符之间精确的时序?
如果您愿意使用Boost,它具有CPU精密计时器 。 如果没有,在Windows上有功能QueryPerformanceCounter
和QueryPerformanceFrequency
,这可以用于基于CPU的时间,这肯定会满足您的所有需求。 有很多定时器类实现的网络上,他们中的一些在Windows工作都和* IX系统。
第一个问题是,你需要知道有多少音频已通过音频设备通过。 如果您的等待时间足够低,你也许能够从危害您通过推的数据量猜测,但与播放之间的延迟是一个移动的目标,所以你应该尝试从音频信息硬件。 在信息可用,所以使用它,因为“抖动”,你会在延迟的测量误差得到可以在音乐上明显的方式实现同步。
如果必须使用睡眠时间,有两个问题,这将使它睡眠时间:1,优先级(如果另一个进程/线程的优先级更高,它会运行,如果计时器是否用完)和2系统的延迟(如果该系统需要5毫秒交换进程/线程,它可以添加到您请求的延迟时间)。 这些类型的延迟是音乐相关。 大多数MIDI的API有“序”的API,可以让你提前排队数据,以避免使用系统计时器。
即使你不使用portaudio音频I / O您可能会发现这个文件非常有用。
http://www.portaudio.com/docs/portaudio_sync_acmc2003.pdf
这个问题的答案不在于小的缓冲区,但路数。
让我们有3分钟的歌曲的一个例子。
一个第一渲染数字部分,和“标签”将其与MIDI音符。 然后一个人开始玩它,并触发MIDI音符时,它的时候,可能使用一个std ::矢量持有的在次序列表。 该同步可以通过使用整体的时间偏移被改变:
在话题太可怕了不完整的,但希望示范伪代码:
start_digital_playing_thread();
int midi_time_sync = 10; // ms
if (time >= (midi_note[50]->time + midi_time_sync)) // play note