录音/混音器软件
Posted
技术标签:
【中文标题】录音/混音器软件【英文标题】:Audio Recording/Mixer Software 【发布时间】:2013-06-25 19:16:28 【问题描述】:作为一名吉他手,我一直想开发自己的录音、混音软件。我在 Direct Sound、Windows 多媒体(waveOutOpen 等)方面有一些经验。我意识到这将是一个复杂的项目,但纯粹是为了我自己的使用和学习,即没有截止日期!我打算使用 C++,但还不确定它是最好的 SDK/API。我希望软件是可扩展的,因为我可能希望在将来添加效果。一些先决条件...
-
在 Windows XP 上运行
最小延迟
VU 表(在所有轨道上)
这导致我回避 Direct Sound,因为似乎没有办法从主缓冲区读取音频数据。
配音(即在播放现有曲目的同时录制新曲目)。
包括节拍器
我最初的想法是使用WMM并使用waveOutWrite函数来播放音频数据。我想这本质上是一个音频流播放器。为了让事情更简单,我将采样率硬编码为 16 位,44.1kHZ(我的声卡支持的最佳采样率)。我需要的是关于整体架构的一些想法和指导。
例如,假设我的速度是 60 BPM,拍号是 4/4。我希望节拍器在每个小节/小节的开头播放一个咔嗒声。现在假设我已经录制了节奏音轨。播放时,我需要编排(双关语)将哪些数据发送到主声音缓冲区。在某些时候,我可能还想添加乐器、鼓(主要是)。同样,我需要知道如何在正确的时间将正确的音频数据发送到主音频缓冲区。我很欣赏时机是这里的关键。我不确定的是如何从各个音轨中获取正确的数据以发送到主声音缓冲区。
我最初的想法是有一个定时线程,它会定期询问每个曲目,“我需要数据来覆盖 N 毫秒的播放时间”。其中 N 取决于主缓冲区大小。
我明白这是一个复杂的问题,我只需要一些关于如何解决上述问题的指导。
另一个问题是 WMM 或 DirectSound 更适合我的需求。甚至ASIO?但是,主要问题是如何使用流式传输机制收集正确的轨道数据(来自多个轨道)以发送到主缓冲区,并保持最小的延迟?
感谢您的帮助,
非常感谢
卡尔
感谢您的回复。但是,我的主要问题是如何对所有这些进行计时,以确保每个轨道在正确的时间将适当的数据写入主缓冲区。我当然欢迎(免费)图书馆,这将帮助我实现我的主要目标。
【问题讨论】:
关于 API 选择的说明:从 Vista 开始,一个新的 API (WASAPI) 通过其exclusive-mode streams 专门针对低延迟音频。这是在 Windows 中处理低延迟音频的最佳简便方法。在 XP 中类似的低延迟我想你将不得不使用 ASIO。 谢谢 Roman,是的,我考虑过 ASIO,因为这纯粹是一个 XP 项目。 当然,您也应该考虑使用 PortAudio,它可以让您访问 ASIO 和其他 API。 您的“主要问题”并不是一个真正的具体问题。您是否尝试过编写任何代码?什么没有奏效?为什么您无法安排多个轨道的缓冲区同时到达? 我不确定如何将正确的轨道数据写入主缓冲区。例如,根据速度和主缓冲区大小,可能需要多次写入节拍器数据。对于先前记录的轨道,我将发送一个等于主缓冲区大小的块,直到所有轨道数据都已发送。根据乔的回答,我想我需要根据主缓冲区大小计算时间范围。然后我可以计算出适合时间范围内的节拍数。然后我可以确定要写入主缓冲区的样本数(节拍器、鼓等)。 【参考方案1】:由于您打算支持 XP(我不会推荐,因为即使扩展支持将在明年结束),您真的别无选择,只能使用 ASIO。可以从Steinberg 下载相应的 SDK。在 Windows Vista 及更高版本中,WASAPI Exclusive Mode 可能是更好的选择,因为可用性更广,但是文档严重缺乏 IMO。在任何情况下,您都应该看看 PortAudio,它有助于包装这些 API(与 Juce 不同的是,它是免费的。
WMM、DirectSound 和 XAudio 2 都无法为实时监控实现足够低的延迟。低延迟 API 通常会定期为每个数据块调用回调。
由于每个回调处理给定数量的样本,您可以根据采样率和样本计数器计算时间(只需在回调调用中累积)。提示:不要用浮点数累加。那就是疯狂。使用 64 位采样计数器,因为最小的增量总是1./sampleRate
。
实际上,您的回调函数将(对于每个轨道)调用 getSamples(size_t n, float* out)
(或类似的)方法并总结结果(即混合它们)。然后,每个单独的轨道都可以有一个集成的采样时间来计算当前需要什么。对于周期性事物(无限波、循环、节拍器),您可以轻松计算每个周期的样本数并拥有一个模数计数器。这会导致周期四舍五入,但如前所述,浮点累加器是禁忌,但它们可以正常处理周期信号。
在节拍器示例中,您可能有一个波形“click.wav”,其中包含n
样本和一段m
样本。您的计数器会定期从0
变为m-1
,只要计数器小于n
,您就会播放相应的波形样本。例如,一个简单的节拍器会在每个节拍上播放一个咔嗒声,它可能看起来像这样:
class Metronome
std::vector<float> waveform;
size_t counter, period;
public:
Metronome(std::vector<float> const & waveform, float bpm, float sampleRate) : waveform(waveform), counter(0)
float secondsPerBeat = 60.f/bpm; // bpm/60 = bps
float samplesPerBeat = sampleRate * secondsPerBeat;
period = (size_t)round(samplesPerBeat);
void getSamples(size_t n, float* out)
while(n--)
*out++ = counter < waveform.size() ? waveform[counter] : 0.f;
counter += 1;
counter -= counter >= period ? period : 0;
;
此外,您可以在 Internet 上查看 VST/AU 插件编程教程,因为它们具有从样本数量确定时间的相同“问题”。
【讨论】:
谢谢乔,我并没有建议为每首曲目设置一个单独的线程,那太疯狂了 :-) 我目前在工作时也使用 XP。 我猜我看错了那句话。在任何情况下,您都不需要自己的“定时线程”,因为会定期调用回调(它将在不同的线程中,甚至可能在中断处理程序中)。 这仍然是一个问题,我该如何安排这一切。有些样本需要经常播放(即节拍器)。然而,其他轨道需要将数据流式传输到主缓冲区。正如我最初问的那样,我需要一些架构方面的指导:-) Juce 拥有双重 GPL 和商业许可。上次我为商业(例如封闭源代码)使用定价时,它非常合理且很容易证明它附带的支持是合理的。对于 OP 的预期目的,它还具有比 PA 更有用的功能。 是的。不过,我不认为 GPL 是免费的。我只是想提供另一种选择,如果 Juce 对于 OP 来说太贵了,我认为可能考虑到他仍然使用 XP。【参考方案2】:正如你所发现的,你正在进入一个痛苦的世界。如果您真的在为 Windows XP 构建音频软件并期望低延迟,那么您肯定希望避免操作系统提供的任何音频 API,并且像几乎所有商业软件一样使用 ASIO。虽然情况有所好转,但 ASIO 不会很快消失。
为了大大减轻您的痛苦,我建议您查看Juce,这是一个用于构建音频主机软件和插件的跨平台框架。它已被用于构建许多商业产品。
他们涵盖了许多真正令人讨厌的架构危害,并附带了主机应用程序和插件的示例。
【讨论】:
谢谢马尔科,是的,我期待一个痛苦的世界。出于兴趣,Juce 必须在某些时候使用操作系统功能。它使用ASIO吗?我只是想了解最好的前进方式:-) 看起来是这样——尽管在多大程度上我不知道在哪些平台上(例如在 MacOSX 上,ASIO 是 CoreAudio 之上的一个薄垫片)。然而,关键是 Juce 抽象这些令人讨厌的细节远离你,但提供了一个低延迟的信号路径。以上是关于录音/混音器软件的主要内容,如果未能解决你的问题,请参考以下文章