【问题标题】:How accurately (in terms of time) does Windows play audio?Windows 播放音频的准确度(就时间而言)如何?
【发布时间】:2011-01-27 12:19:01
【问题描述】:

假设我播放一个包含 317,520,000 个样本的立体声 WAV 文件,理论上需要 1 小时。假设播放没有中断,文件会在恰好一小时内完成播放吗,或者播放速度是否偶尔会有一些微小的变化,以至于它会稍微多一些或稍微少一些(通过一些毫秒)超过一小时?

我正在尝试将动画与音频同步,并且我正在使用System.Diagnostics.Stopwatch 来保持帧与音频匹配。但是,如果 Windows 中 WAV 音频的播放速度会随着时间的推移而略有变化,那么音频将与秒表驱动的动画不同步。

这导致了第二个问题:似乎Stopwatch - 虽然在短时间内高度精细且准确 - 运行速度略快。在我的笔记本电脑上,Stopwatch 运行了 24 小时(由计算机的系统时间和真正的秒表测量)显示 24 小时的经过时间加上大约 5 秒(不是毫秒)。

这是Stopwatch 的已知问题吗? (一个相关的问题是“我疯了吗?”,但您可以自己尝试一下。)鉴于它用作诊断工具,我可以看到只有在测量长持续时间时才会出现这样的差异,其中大多数人们会使用 Stopwatch 以外的其他东西。

如果我真的很幸运,那么Stopwatch 和音频播放都是由相同的底层机制驱动的,因此会连续几天保持同步。这是真的吗?

更新:我刚刚算了一下,如果Stopwatch 在 24 小时内漂移 5 秒,这意味着它会在 172 秒后漂移 10 毫秒。所以在 3 分钟后,动画将开始明显不同步。

我正在尝试定期(每 10 秒左右)从 waveOutWrite 回调重新启动计时器,但这不起作用,因为无论回调的不准确性如何,整个下一组计时器事件都会被抵消碰巧是。真讨厌我。

【问题讨论】:

  • 你怎么知道你的“真正的秒表”没有跑慢?
  • @Ben S:还用台钟(带秒)和另一台 PC 进行计时。除了Stopwatch,所有东西都有相同的时间给予或花费半秒。我只是因为另一个 StackOverflow 问题才尝试这个,有人提到 Stopwatch 在他们的 PC 上每 24 小时快速运行大约 10 秒。我很乐意看到其他人证实/驳斥这一点。
  • 不能为此设置一些测试吗?我相信你可以从华盛顿的原子钟上采样时间,然后在八小时左右的时间内使用秒表和其他机制,并建立一个相对准确度的图表......
  • 有趣,我要给它加星标看看它的去向。您是否搜索过有关此问题的错误报告?我本以为现在有人会发现这一点,除非Stopwatch 文档明确指出它只能在短时间内使用。

标签: .net windows audio


【解决方案1】:

没有时钟可以“准确”测量时间,因为所有物理设备都必然会有一些变化和测量误差。这意味着所有时钟都会稍微太快或太慢(尽管误差量可能会有很大差异,具体取决于时钟)。

在您的情况下,音频输出由驱动 DAC 的声卡上的时钟驱动。我不知道 .NET 平台,但我认为 Stopwatch 是某种系统计时器,这意味着它由不同的时钟(大概是主板上的时钟)驱动。

现在,一般来说,两个不同的物理时钟永远不会以完全相同的速度运行 - 出于上述原因。这就是你得到的差异的来源。您的动画也会发生同样的事情 - 您可以绝对不要假设系统时钟和声卡 DAC 时钟相同 - 它们会有所不同!

这意味着如果您想保持两个流(视频和音频)同步,它们必须由相同的时钟驱动。由于您无法更改驱动声卡的时钟,因此最好将所有内容同步到声卡。

【讨论】:

  • 我认为你是绝对正确的,音频速度将由声卡上的芯片驱动,而秒表不可能由同一个芯片驱动。我在与声卡同步时遇到的问题是我正在使用的 API(waveOutOpen 和 waveOutWrite)通过消息与调用应用程序进行通信,因此虽然这些事件通常与音频保持同步,但它们的时间非常不规律动画明显不流畅(我不得不改用秒表来使动画流畅)。
  • 基本上,秒表对于流畅的动画来说足够精确,但最终会与音乐不同步。 waveOut 回调永远保持同步,但对于动画来说不够平滑。我需要想出一些将两者结合起来的方法,比如使用回调来定期调整秒表。
  • FWIW,在 Windows 中,视频时钟由音频时钟驱动。如果您正在渲染音频,您可以通过调用 waveOutGetPosition 来获取音频时钟(因为音频是同步的,所以位置与时间直接相关)。所有其他音频渲染 API 都有一个类似的“GetPosition”API,可用于确定音频渲染位置。
  • @MusiGenesis:Win32 消息通常不适用于对时间敏感的通信。尝试请求回调而不是消息。另外,请注意,对于如此高的同步要求,使用 DirectSound 之类的 API 可能会更好。
  • @Larry:感谢您提供此信息。我觉得自己像个傻瓜,因为不知道专门为这个问题设计的方法。我最近才开始制作足够复杂的动画,以至于我注意到 waveOutWrite 回调的时间有点不稳定。
【解决方案2】:

Larry Osterman 在评论中提供了答案:

FWIW,在 Windows 中,视频时钟是 由音频时钟驱动。如果你是 渲染音频,你得到音频 通过调用 waveOutGetPosition 时钟 (因为音频是同步的,所以 位置与 时间)。所有其他音频渲染 API 具有类似的“GetPosition”API 可用于确定 音频渲染位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多