使用软件合成器制作实时音频应用程序

3
我正在研究开发一款软件,使键盘的功能类似于钢琴(例如,用户按下“W”键,扬声器会播放D音符)。我可能会使用OpenAL。我了解数字音频的基础知识,但是在响应按键时实时播放音频会带来一些问题,我很难解决。
这里是问题:假设我有10个音频缓冲区,每个缓冲区都保存一秒钟的音频数据。如果我必须在它们被播放之前填充缓冲区,那么我将在它们播放前一两秒钟填充缓冲区。这意味着无论用户何时尝试播放一个音符,在按下按键和播放音符之间都会有一到两秒的延迟。
如何解决这个问题?你只需尽可能地使缓冲区变小,并尽可能晚地填充它们吗?还是有什么技巧我没有掌握?
3个回答

6

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

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

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

这将给您一个恒定的延迟,该延迟仅受到您的环形缓冲区大小和声卡输出延迟(通常不是很大)的限制。

您甚至可以进一步降低延迟:

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

如果您正在运行基于时间的效果(延迟线、混响等),这就变得棘手了,但是有解决方法。每一毫秒左右跟踪您的基于时间的效果的最后10个状态即可。这将使您能够在时间上回退10毫秒。


这很有道理。你能推荐一些适合这种单个环形缓冲区方法的音频库吗? - Tom Dalling
是的,在Win32上,它是directsound。就这么简单。对于Linux,我不太清楚。最有可能是ALSA。对于纯硬件解决方案(例如嵌入式设备),您不想使用任何API,而是希望从中断处理程序中调用您的例程。 - Nils Pipenbrinck
真的不是所有的软件合成器都使用环形缓冲区,VST和AudioUnits(所以,在它们之间约占市场的90%)都使用小缓冲区的多缓冲区方法。ALSA没有提供DirectShow / Sound或CoreAudio信号图的等效物,但有大量竞争的开源实现。当涉及到开源软合成器的API时,通常会完全使用VST,并且通常依赖于Linux能够链接加载Windows可执行文件的能力。 - marko

1

使用WinAPI,您在延迟方面只能做到这么多。通常情况下,您无法低于40-50毫秒,这相当糟糕。解决方案是在您的应用程序中实现ASIO支持,并使用户在后台运行类似于Asio4All的东西。这将把延迟降至5毫秒,但代价是:其他应用程序无法同时播放声音。

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


0

解决方案是通过实时线程频繁填充小缓冲区。您可以使用环形缓冲区,将缓冲区的大小(或其达到的满度)限制在操作系统的调度延迟范围内,一般情况下10毫秒是可以接受的。

对于未经训练者来说,这里有一些令人担忧的陷阱,特别是关于软件架构和线程安全方面的问题。

您可以尝试查看Juce - 这是一个跨平台的写入音频软件的框架,尤其是用于软件合成器和音效插件。它包括为样本插件和主机编写的软件。主要处理与线程相关的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接