使用软件合成器制作实时音频应用程序
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 和效果器。它包括用于示例插件和主机的软件。主要是在主机中处理线程问题。
【讨论】:
以上是关于使用软件合成器制作实时音频应用程序的主要内容,如果未能解决你的问题,请参考以下文章