waveOutWrite API方法回调的延迟(或延迟)时间是多少?

时间:2009-08-20 03:37:48

标签: windows audio waveout waveoutwrite

我正在与另一个论坛上的一些开发人员就准确生成MIDI事件(Note On messages等)进行辩论。人耳对于轻微的定时误差非常敏感,我认为他们的主要问题来自于他们使用相对低分辨率的定时器,这些定时器以大约15毫秒的间隔量化它们的事件(这足以引起可察觉的不准确性)。

大约10年前,我编写了一个示例应用程序(Windows 95上的Visual Basic 5),它是一个组合的软件合成器和MIDI播放器。基本前提是一个蛙跳缓冲回放系统,每个缓冲区是十六分音符的持续时间(例如:每分钟120个四分音符,每个四分音符是500毫秒,因此每个十六分音符是125毫秒,所以每个缓冲液是5513个样品)。每个缓冲区都通过waveOutWrite方法播放,此方法的回调函数用于排队下一个缓冲区并发送MIDI消息。这使基于WAV的音频和MIDI音频保持同步。

在我看来,这种方法运作得非常完美 - MIDI音符听起来甚至没有声音(如果你使用一个精确到15毫秒的普通计时器来播放MIDI音符,它们会听起来明显不合适)。 / p>

理论上,这种方法可以产生对样本准确的MIDI定时,或0.0227毫秒(因为每毫秒有44.1个样本)。我怀疑这是这种方法的真正延迟,因为在缓冲区完成和通知waveOutWrite回调之间可能存在一些轻微的延迟。有谁知道这种延迟实际上有多大?

3 个答案:

答案 0 :(得分:5)

默认情况下,Windows调度程序以10毫秒或16毫秒的间隔运行,具体取决于处理器。如果使用timeBeginPeriod()API,则可以更改此间隔(以相当大的功耗成本)。

在Windows XP和Windows 7中,wave API以大约30ms的延迟运行,对于Windows Vista,wave API的延迟大约为50ms。然后,您需要添加音频引擎延迟。

不幸的是,我没有一个方向的引擎延迟数字,但我们确实有一些关于引擎延迟的数字 - 我们运行了一个测试,通过USB音频设备播放音调并测量往返延迟(渲染捕捉)。在Vista上,往返延迟约为80毫秒,变化约为10毫秒。在Win7上,往返延迟约为40毫秒,变化约为5毫秒。然而,YMMV因为音频硬件引入的延迟量对于每个硬件都是不同的。

我完全不知道XP音频引擎或Win9x音频堆栈的延迟是什么。

答案 1 :(得分:1)

在最基本的层面上,Windows是一个多线程操作系统。它以100ms的时间片调度线程。 这意味着,如果没有CPU争用,缓冲区结束和waveOutWrite回调之间的延迟可以是任意短的。或者,如果有其他忙线程,则每个线程必须等待100毫秒。 然而,在最好的情况下...... CPU速度现在以GHz为单位。这使得回调在0.000,000,000,1第二个数量级内的调用速度有绝对下限。

除非您能够计算出一秒钟内可以处理的waveOutWrite回调的最大数量,这可能意味着每次调用的延迟,我认为实际上,延迟将低于大多数情况下的延迟。时间,除非有太多繁忙的线程,在这种情况下它会变得非常可怕,可怕的错误。

答案 2 :(得分:1)

添加上面的好答案。

你的问题是关于Windows既没有承诺不关心的延迟。因此,根据操作系统版本,硬件和其他因素,它可能会有很大差异。 WaveOut API和DirectSound(不确定WASAPI,但我想这个最新的Vista +音频API也是如此)都设置为缓冲音频输出。只要在电流仍在播放的同时排队下一个缓冲区,就不需要特定的回调准确度。

当您开始音频播放时,您有一些假设,例如播放期间没有下溢且所有输出都是连续的,并且音频时钟频率与您预期的完全相同,例如精确地为44,100 Hz。然后,您可以进行简单的数学运算,及时安排波形输出,将时间转换为采样,然后转换为字节。

可悲的是,有效播放率并不准确,例如想象实际硬件采样率可能是44,100 Hz -3%,从长远来看,时间到字节的数学可能会让你失望。已经尝试补偿这种效果,例如使音频硬件成为回放时钟并使视频与其同步(这是播放器的工作方式),以及速率匹配技术以将输入数据速率与硬件上的实际回放速率相匹配。这两者都使得绝对时间测量和延迟成为一种推测性知识。

更多内容,API延迟为20毫秒,30毫秒,50毫秒等。很久以前,waveOut API就是其他API之上的一个层。这意味着某些处理在数据实际到达硬件之前进行,并且此处理要求您提前将手放在排队的数据上,否则数据将无法到达硬件。假设您尝试在播放时间之前将数据排入10 ms缓冲区,API将接受此数据,但是它会在下游传递此数据,并且扬声器上会出现静音或舒适噪音。

现在这也与您收到的回调有关。你可以说你不关心缓冲区的延迟,对你来说重要的是精确的回调时间。但是,由于API是分层的,您可以按照内层同步的准确性接收回调,这样第二个内层通知空闲缓冲区,第一个内层更新其记录并检查它是否也可以释放缓冲区(嘿,那些缓冲区不是'我必须匹配)。这使得回调准确性期望真的很弱且不可靠。

如果我没有触及waveOut API很长一段时间,如果出现这样的同步准确性问题,我可能首先会想到两件事:

  • Windows提供对音频硬件时钟的访问(我知道通过DirectShow可以获得IReferenceClock接口,它可能来自另一个可以访问的低级别的东西)并且有可用的我会尝试与它同步< / p>

  • 来自Microsoft的最新音频API,WASAPI,为低延迟音频提供特殊支持,其中包括更好的媒体线程调度,独占模式流和PCM的10毫秒延迟 - 这是更好的同步