PortAudio:通过调用函数播放多个生成的声音

时间:2017-12-10 15:18:00

标签: c++ audio portaudio

我在一周前开始玩PortAudio库。我检查了大部分教程/测试示例,但没有看到我需要的解决方案。我正在制作简单的音序器 - 我已经在钢琴卷上做了绘画声音作为块,但现在我需要以某种方式使它听起来。我想知道是否有可能让它像这样工作:

  • 运行一种播放一种声音的方法,
  • 将声音的频率和持续时间作为该方法的参数,
  • 播放多个声音(即同时播放三个声音,调用三种方法)。

在示例文件中,它看起来更复杂。当我想播放多个正弦波时,我必须合并所有波形,然后将数据提供给流。

也许有人有更好的解决方案来解决这个问题?

2 个答案:

答案 0 :(得分:1)

我只会给你一个简单的例子(对于sine wave)然后你可以创建你感兴趣的其他类型的波。所需的输入参数是

  
      
  • 采样率(例如8000,16000等)
  •   
  • 幅度(实际值取决于输出格式,但最好是在0-1范围内的值,并将它们转换为任何格式   你喜欢/需要)
  •   
  • 频率(表示为采样率的一部分)
  •   
  • 持续时间(以秒为单位)
  •   

音调数据(样本)的缓冲区长度由tone duration以秒为单位乘以sampling rate确定。

创建正弦波的实际代码可能类似于以下内容

//global variables
const float PI = 3.141593;
const unsigned samplingRate = 8000;
const float amp = 0.8;

float *GenerateTone(float frequency, unsigned duration, unsigned &bufferLen){

     const float freq = frequency/samplingRate; //(e.g 440 / 8000 = 0,055)

     bufferLen = samplingRate * duration;

     float *buffer = new float[bufferLen]

     for(int i = 0; i < bufferLen; i++ ){

        buffer[i] = amp * sin(2 * PI*freq  * ((float)i)/samplingRate);

        }
    return buffer;
}   

您可以将此功能称为

unsigned len;
float *pTone = GenerateTone(440, 1, len);//len is an out parameter
...
delete [] pTone; //deallocatone memory when you no longer need it

在C ++中,您还可以使用std::vector来存储样本。这样您就不必担心内存分配/释放。

std::vector<float> v; //make vector global  
const float PI = 3.141593;
const unsigned samplingRate = 8000;
const float amp = 0.8;

void GenerateTone(float frequency, unsigned duration){

  const amp = 0.8f;

  const float freq = frequency/samplingRate; 

  const unsigned len = samplingRate * duration; 
  for(int i = 0; i < len; i++ )
        v.push_back(amp * sin(2*PI*freq  * ((float)i)/sampleRate));

}

您也可以将幅度作为参数传递,但在上面的示例中,幅度是硬编码的。另请参阅(https://en.wikipedia.org/wiki/Triangle_wavehttps://en.wikipedia.org/wiki/Square_wave

答案 1 :(得分:0)

以上程序是生成音频的一种快速方法。 小修正: 代替

const float freq = frequency/samplingRate; 

应为: const float freq = frequency; //即将频率直接传递到sin()