我正在研究制作一些使键盘功能像钢琴一样的软件(例如,用户按下'W'键,扬声器播放D音符)。我可能会使用OpenAL。我理解数字音频的基础知识,但是在按键时播放实时音频会带来一些我难以解决的问题。
问题在于:假设我有10个音频缓冲区,每个缓冲区都有一秒的音频数据。如果我必须在通过扬声器播放之前填充缓冲区,那么我会在播放前一两秒填充缓冲区。这意味着每当用户尝试播放音符时,按键和正在播放的音符之间将有一到两秒的延迟。
你如何解决这个问题?你是否只是让缓冲区尽可能小,并尽可能地填充它们?是否有一些我不知道的伎俩?
答案 0 :(得分:6)
大多数软件合成器根本不使用多个缓冲区。
他们只使用一个不断播放的小型铃声。
高优先级线程将尽可能多地检查当前播放位置并填充带有声音数据的铃声缓冲器的自由部分(例如,自上次线程运行以来已播放的部分)。
这将为您提供恒定的延迟,该延迟仅受环形缓冲区大小和声卡输出延迟的限制(通常不会那么多)。
您可以进一步降低延迟:
如果要播放新音符(例如用户刚按了一个键),则检查环形缓冲区内的当前播放位置,添加一些样本以确保安全,然后使用应用了新的声音设置。
如果您运行基于时间的效果(延迟线,混响等),这会变得棘手,但它是可行的。只需跟踪每毫秒左右基于时间的效果的最后10个状态。这样就可以在10毫秒内恢复。
答案 1 :(得分:1)
使用WinAPI,您只能在延迟方面达到目前为止。通常你不能低于40-50ms这是非常讨厌的。解决方案是在您的应用程序中实现ASIO支持,并让用户在后台运行类似Asio4All的东西。这会将延迟降低到5毫秒,但需要付出代价:其他应用无法同时播放声音。
我知道这是因为我是FL Studio用户。
答案 2 :(得分:0)
解决方案是小缓冲区,由实时线程频繁填充。缓冲区的大小(或缓冲区使缓冲区变满的程度)受到调度操作系统延迟的限制。你可能会发现10毫秒是可以接受的。
这里有一些令人讨厌的问题,对于那些没有经验的人来说 - 特别是在软件架构和线程安全方面。
您可以尝试查看Juce - 这是一个用于编写音频软件的跨平台框架,特别是 - SoftSynths和效果等音频插件。它包括用于示例插件和主机的软件。在主机中,主要处理线程问题。