3

我正在研究制作一些使键盘功能像钢琴一样的软件(例如,用户按下“W”键,扬声器播放 D 音符)。我可能会使用 OpenAL。我了解数字音频的基础知识,但是响应按键播放实时音频会带来一些我无法解决的问题。

问题是:假设我有 10 个音频缓冲区,每个缓冲区保存一秒钟的音频数据。如果我必须在通过扬声器播放缓冲区之前填充缓冲区,那么我将在播放缓冲区前一两秒填充缓冲区。这意味着每当用户尝试弹奏一个音符时,在按键和播放音符之间会有一到两秒的延迟。

你如何解决这个问题?您是否只是使缓冲区尽可能小,并尽可能晚地填充它们?有什么我错过的技巧吗?

4

3 回答 3

6

大多数软件合成器根本不使用多个缓冲区。

他们只使用一个不断播放的小型环形缓冲区。

一个高优先级的线程会尽可能多地检查当前播放位置,并用声音数据填充环形缓冲区的空闲部分(例如,自上次运行线程以来播放的部分)。

这将为您提供一个恒定的延迟,该延迟仅受环形缓冲区大小和声卡输出延迟的限制(通常不会那么多)。

您可以进一步降低延迟:

如果要播放新音符(例如用户刚刚按下一个键),您检查环形缓冲区中的当前播放位置,添加一些样本以确保安全,然后使用新声音重新渲染声音数据 -应用的设置。

如果您运行基于时间的效果(延迟线、混响等),这会变得很棘手,但它是可行的。只需每毫秒左右跟踪一次基于时间的效果的最后 10 个状态。这将有可能及时返回 10 毫秒。

于 2009-09-08T08:57:01.343 回答
1

使用 WinAPI,您只能在延迟方面做到这一点。通常你不能低于 40-50ms,这是非常讨厌的。解决方案是在您的应用程序中实现 ASIO 支持,并让用户在后台运行类似 Asio4All 的东西。这将延迟降低到 5 毫秒,但代价是:其他应用程序无法同时播放声音。

我知道这一点,因为我是 FL Studio 用户。

于 2010-09-08T17:45:29.393 回答
0

解决方案是小型缓冲区,由实时线程频繁填充。缓冲区的大小(或环形缓冲区让缓冲区变得多满)受操作系统的调度延迟限制。您可能会发现 10 毫秒是可以接受的。

对于初学者来说,这里有一些令人讨厌的陷阱——尤其是在软件架构和线程安全方面。

您可以尝试查看Juce - 这是一个用于编写音频软件的跨平台框架,特别是 - 音频插件,如 SoftSynths 和效果器。它包括用于示例插件和主机的软件。主要是在主机中处理线程问题。

于 2012-12-30T18:27:35.707 回答