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

Posted

技术标签:

【中文标题】使用软件合成器制作实时音频应用程序【英文标题】:Making a real-time audio application with software synthesizers 【发布时间】:2009-09-08 08:31:34 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

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

您可以进一步降低延迟:

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

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

【讨论】:

这是有道理的。你能推荐任何适合这种单环形缓冲区方法的音频库吗? 是的。在 Win32 上它是直接声音。就这么简单。对于Linux,我真的不知道。很可能是ALSA。对于纯硬件解决方案(例如嵌入式事物),您根本不需要任何 API,但希望从中断处理程序中调用您的例程.. “大多数”软件合成器都在使用环形缓冲区是不正确的——VST 和 AudioUnits(因此,它们之间大约 90% 的市场)都使用带有小缓冲区的多缓冲区方法. ALSA 不提供 DirectShow/Sound 或 CoreAudio 信号图的等价物,但有大量竞争的开源实现。当谈到开源软件合成器的 API 时,它往往是 VST,通常依赖于 Linux 链接加载 Windows 可执行文件的能力。【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

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

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

【讨论】:

以上是关于使用软件合成器制作实时音频应用程序的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Windows 语音合成器说话时显示音频波?

基本软件合成器的延迟随着时间的推移而增长

Python使用ffmpeg合成视频音频

影片合成

使用软件合成器将 MIDI 文件转换为原始音频

关于如何在视频中合成声音