在准确的时刻播放声音

Posted

技术标签:

【中文标题】在准确的时刻播放声音【英文标题】:Play sound at an exact moment 【发布时间】:2015-01-25 21:31:02 【问题描述】:

我想播放一个声音样本(大约 2 分钟长)并在播放样本时记录击键。我需要知道按键的确切时间相对于播放开始时间,分辨率为 1 毫秒或更短。

首先我尝试了NAudio 和一个Winforms 应用程序。我发现同步播放开始时间和击键时间是完全不可能的。我知道何时开始将样本字节传输到 NAudio,但不知道传递样本和实际播放之间的时间。我也知道我的应用程序接收 KeyDown 事件的时间,但不知道事件从键盘硬件一直到我的 C# 事件处理程序的实际时间。

这或多或少是准确的 - 我在应用程序报告的延迟和实际延迟之间有 270 毫秒(+- 5 毫秒)的延迟(我通过记录会话和查看示例文件知道实际延迟。录音是在不同的设备上完成的,当然不是运行应用程序的计算机...)。

这还不够好,因为 +- 5ms。即使我在播放期间禁用了第 2 代 GC,也会发生这种情况。我需要比这更准确。

我不介意切换到 C++ 和非托管代码,但我想知道使用哪个声音播放 API,以及是否有比等待 WM_KEYDOWN 消息更准确的方法来获取键盘输入。

【问题讨论】:

至于击键时间戳,请查看缓冲模式下的DirectInput。它应该为您提供每个事件的高分辨率时间戳。我不确定您将如何将其与音频时间相关联。我知道在DirectSound 中,您可以确切地找到播放在缓冲区中的位置,因此可以准确地计算出您相对于播放开始的毫秒数,但我不知道是否有一个好的方法来改变它进入一个绝对时间。 【参考方案1】:

使用 NAudio,所有实现IWavePosition 接口的输出设备都可以准确报告播放位置的准确位置。准确地了解如何将位置转换为时间可能需要一些尝试和错误,但这是解决此问题的最佳方法。

【讨论】:

以上是关于在准确的时刻播放声音的主要内容,如果未能解决你的问题,请参考以下文章

如何确切地知道为啥声音开始播放?

(iphone) 如何使用 AVAudioPlayer 顺序播放声音?

准确的跨平台声音处理

在 iPhone 上完美连续播放声音

推送到达时未播放自定义声音

使用 GCD 计时器间隔播放声音未按预期运行