录音/混音器软件

时间:2013-06-25 19:16:28

标签: c++ audio windows-xp

作为一名吉他手,我一直想开发自己的录音,混音软件。我在Direct Sound,Windows Multimedia(waveOutOpen等)方面有一些经验。我意识到这将是一个复杂的项目,但纯粹是为了我自己的使用和学习,即没有最后期限!我打算使用C ++,但目前还不确定是最好的SDK / API。我希望软件是可扩展的,因为我希望将来添加效果。一些先决条件......

  1. 在Windows XP上运行
  2. 最小延迟
  3. VU表(在所有轨道上) 这导致我回避直接声音,因为似乎没有办法从主缓冲区读取音频数据。
  4. 配音(即在播放现有曲目时录制新曲目)。
  5. 包括节拍器
  6. 我最初的想法是使用WMM并使用waveOutWrite函数播放音频数据。我想这实际上是一个音频流媒体播放器。为了让事情变得更简单,我会将采样率硬编码为16位,44.1kHZ(我的声卡支持的最佳采样率)。我需要的是一些想法,整体架构的指导。

    例如,假设我的节奏是60 BPM,时间签名是4/4。我希望节拍器在每个小节/小节的开头点击一下。现在假设我录制了一首节奏音轨。在播放时,我需要协调(双关语)将哪些数据发送到主声音缓冲区。在某些情况下,我也可能想要添加乐器,鼓(主要是)。同样,我需要知道如何在正确的时间将正确的音频数据发送到主音频缓冲区。我很欣赏时机是关键。我不确定的是如何从各个轨道中获取正确的数据以发送到主声音缓冲区。

    我最初的想法是有一个定时线程,定期询问每个轨道,“我需要数据来覆盖N毫秒的播放”。其中N取决于主缓冲区大小。

    我理解这是一个复杂的问题,我只需要一些关于如何处理上述问题的指导。

    另一个问题是WMM或DirectSound更适合我的需求。也许甚至ASIO?但是,主要的问题是,如何使用流机制,我是否收集正确的跟踪数据(来自多个轨道)以发送到主缓冲区,并保持最小的延迟?

    感谢任何帮助,

    非常感谢

    卡尔

    感谢您的回复。但是,我的主要问题是如何计算所有这些,以确保每个轨道在正确的时间将适当的数据写入主缓冲区。我当然对(免费)图书馆开放,这将帮助我实现我的主要目标。

2 个答案:

答案 0 :(得分:2)

由于您打算支持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;
        }
    }
};

此外,您可以在互联网上查看VST / AU插件编程教程,因为它们与样本数量确定时间有相同的“问题”。

答案 1 :(得分:1)

正如您所发现的,您正在进入痛苦的世界。如果您真的正在为Windows XP构建音频软件并期望低延迟,那么您肯定希望避免操作系统提供的任何音频API,并且几乎所有商业软件都会使用ASIO。虽然事情变得更好,但ASIO不会很快就会继续前进。

为了大大减轻您的痛苦,我建议您查看Juce,这是一个用于构建音频主机软件和插件的跨平台框架。它已被用于构建许多商业产品。

它们涵盖了许多非常令人讨厌的架构风险,它附带了主机应用程序和插件的示例。