2012-07-26 193 views
3

因此,我在长时间的停顿之后选择了C++,并且我有一个想法来创建一个可以在运行时基于数字串生成音乐的程序(受到某些人完成的composition of Pi的启发),最终目标是某种程序性音乐生成软件。使用C++在运行时生成声音

到目前为止,我已经能够使用Beep()函数制作出一个非常原始的版本,并且通过Pi的第一个左右数字作为测试。奇迹般有效。

什么我要找的是现在我怎么会踢它了一个缺口,并得到一些更高品质的声音正在取得(因为蜂鸣()字面上是最原始的声音......有的话),我意识到我绝对不知道如何做到这一点。我需要的是一个库或某种API,可以:

1)生成没有预先存在的文件的声音。我希望结果是由代码生成的100%,而不是依赖任何样本,最佳。 2)如果我能找到一些能够一次播放多个声音的东西,比如能够打一个和弦或一个节奏的旋律,那就太好了。 3)如果我能以任何方式通过方程式或其他类型的数据控制其播放的波形(有点像chiptune混音器可以),那会非常有帮助。

我不知道这是不是一个奇怪的请求,或者我只是用错误的术语来研究它,但我只是无法找到任何沿着这些线的东西,或者至少没有任何东西被完全记录下来。 :/

如果有人可以帮忙,我会很感激。

编辑:此外,显然我只是超级不习惯问在论坛上的东西,我的目标平台是Windows(7,具体而言,虽然我不认为这件事)。

+0

因此,我假设Windows是因为您提到了'beep()',但您应该真正告诉我们您的目标平台是什么。 C++没有音频的概念,你使用的任何东西都将取决于平台(除非你找到一个从你那里抽象出来的库,但是,这可能不是必需的)。 – 2012-07-26 21:17:15

+0

它将在Windows上,谢谢指出,我会编辑它。 – AniMerrill 2012-07-26 21:18:36

+0

@AniMerrill,我知道没有简单的方法(在Windows API中)为您的程序生成要播放的声音数据。一个图书馆可能是你最好的选择。 – chris 2012-07-26 21:22:17

回答

2

我使用portaudio(http://www.portaudio.com/)。它可以让你以便携的方式创建PCM流。然后你只需将样品推入流中,他们就会播放。

@edit:使用PortAudio非常简单。您初始化库。我使用浮点示例使其变得非常容易。我不喜欢这样写道:

PaError err = Pa_Initialize(); 
if (err != paNoError) 
    return false; 

mPaParams.device = Pa_GetDefaultOutputDevice(); 
if (mPaParams.device == paNoDevice) 
    return false; 

mPaParams.channelCount = NUM_CHANNELS; 
mPaParams.sampleFormat = paFloat32; 
mPaParams.suggestedLatency = 
    Pa_GetDeviceInfo(mPaParams.device)->defaultLowOutputLatency; 
mPaParams.hostApiSpecificStreamInfo = NULL; 

然后,当你想播放声音创建了一个流,2路立体声,在44kHz的,适合MP3音频后:

PaError err = Pa_OpenStream(&mPaStream, 
          NULL, // no input 
          &mPaParams, 
          44100, // params 
          NUM_FRAMES, // frames per buffer 
          0, 
          sndCallback, 
          this 
          ); 

然后你实现回调以填充PCM音频流。该回调函数是一个c函数,但我只需调用我的C++类来处理音频。我从我的代码中撕下了这个,现在可能不是100%正确的,因为我删除了大量你不关心的东西。但它的作品有点像这样:

static int sndCallback(const void*      inputBuffer, 
         void*       outputBuffer, 
         unsigned long     framesPerBuffer, 
         const PaStreamCallbackTimeInfo* timeInfo, 
         PaStreamCallbackFlags   statusFlags, 
         void*       userData) 
{ 
    Snd* snd = (Snd*)userData; 
    return snd->callback((float*)outputBuffer, framesPerBuffer); 
} 

u32 Snd::callback(float* outbuf, u32 nFrames) 
{ 
    mPlayMutex.lock(); // use mutexes because this is asyc code! 

    // clear the output buffer 
    memset(outbuf, 0, nFrames * NUM_CHANNELS * sizeof(float)); 

    // mix all the sounds. 
    if (mChannels.size()) 
    { 
     // I have multiple audio sources I'm mixing. That's what mChannels is. 
     for (s32 i = mChannels.size(); i > 0; i--) 
     { 
     for (u32 j = 0; j < frameCount * NUM_CHANNELS; j++) 
     { 
      float f = outbuf[j] + getNextSample(i) // <------------------- your code here!!! 
      if (f > 1.0) f = 1.0;  // clamp it so you don't get clipping. 
      if (f < -1.0) f = -1.0; 
      outbuf[j] = f; 
     } 
     } 
    } 
    mPlayMutex.unlock_p(); 
    return 1; // when you are done playing audio return zero. 
} 
+0

我见过PortAudio在与这个相关的几个不同主题中弹出,所以我想我可能会给它一个镜头。下载了最新版本,真正让我感到困惑的是,所有的代码都是C而不是C++。我知道它可以完成,但我没有经历两种语言的经验。你有什么建议吗?我目前使用Code :: Blocks IDE和MinGW GCC编译器,如果有帮助的话。 – AniMerrill 2012-07-26 22:29:18

+0

我从我的一个应用程序中剔除了关键位。 – 2012-07-26 22:43:48

+0

谢谢你的帮助,我只是想知道你是否可以帮助我做更多的事情。出于某种原因,我不能在我的生活中弄清楚如何将PortAudio与我的IDE完全链接。我已经编译了它,试图在网上搜索我可能会丢失的内容,但无论我怎么总是忽略重要函数的定义。 就像我可以像...初始化和终止工作的原因,但它不承认任何其他事情。 – AniMerrill 2012-07-29 01:08:26

0

我回答这个本周早些时候在一个非常类似的问题:Note Synthesis, Harmonics (Violin, Piano, Guitar, Bass), Frequencies, MIDI。在你的情况下,如果你不想依赖样本,那么波表方法就没有了。所以最简单的选择是随着时间的推移动态地改变正弦曲线的频率和振幅,这很容易,但听起来很糟糕(就像一个便宜的Theremin)。你唯一真正的选择是一个更复杂的综合算法,如物理建模的一个(例如Karplus-Strong)。这将是一个有趣的项目,但需要警告,它确实需要一些数学背景。

你确实可以像拉斐尔提到的那样使用像Portaudio这样的东西来物理地从PC中取出声音,事实上我认为Portaudio是最好的选择。但生成数据以便听起来很有音乐性是迄今为止最大的挑战。

+0

现在有些东西听起来像是真正的乐器,或者真的比任何一种便宜的东西都好,这是我最担心的 - 至少在这件事情变得更加复杂之前 - 我有点像听起来像cheesy atari音乐。我所要做的是基本构图,希望能有一些便携性,最终可以让我使用更复杂的东西,甚至交出和使用样本。我想在Portaudio听起来不错,我只需要现在就开始工作。 – AniMerrill 2012-07-26 22:57:15

+0

好的。请记住,虽然Portaudio实际上只是一种从声卡中获取原始音频信号的手段 - 它不会帮助您生成任何频率。您必须手动或者找到一个实现这些低级功能的信号处理库。 – 2012-07-27 10:06:20

+0

我对此也很好。所有这个项目都是关于实验的,而不是生产任何有价值的商业或类似的东西。最近才引起我的兴趣。 – AniMerrill 2012-07-29 01:11:39