PortAudio:通过调用函数播放多个生成的声音
PortAudio: Play multiple generated sounds by calling function
我大约一周前开始使用 PortAudio 库。我已经检查了大多数 tutorial/test 示例,但没有看到我需要的解决方案。我正在制作简单的音序器 - 我已经在钢琴卷轴上绘制了作为块的声音,但现在我需要以某种方式让它听起来。我想知道是否有可能让它像这样工作:
- 运行一种播放一种声音的方法,
- 将声音的频率和持续时间作为该方法的参数,
- 播放多个声音(即同时播放三个声音,调用三个方法)。
在示例文件中看起来更复杂。当我想播放多个正弦波时,我必须合并所有这些波,然后将这些数据提供给流。
也许有人有更好的解决方案来解决这个问题?
我只是给你一个简单的例子(对于sine wave
),然后你可以创建你感兴趣的其他类型的波。需要的输入参数是
- sampling rate (e.g 8000, 16000 etc)
- amplitude (the actual values depend on the output format but it's best to have values in the range 0-1 and convert them to whatever format
you like/need)
- frequency (expressed as a fraction of the sampling rate)
- duration (in seconds)
音调数据(样本)的缓冲区长度由 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
来存储样本。这样就不用担心内存了allocation/deallocation.
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_wave, https://en.wikipedia.org/wiki/Square_wave )
以上程序是一种快速生成音频的方法。
小更正:
而不是
const float freq = frequency/samplingRate;
应该是:
const float freq = frequency;
// 即。将频率直接传递到 sin()
我大约一周前开始使用 PortAudio 库。我已经检查了大多数 tutorial/test 示例,但没有看到我需要的解决方案。我正在制作简单的音序器 - 我已经在钢琴卷轴上绘制了作为块的声音,但现在我需要以某种方式让它听起来。我想知道是否有可能让它像这样工作:
- 运行一种播放一种声音的方法,
- 将声音的频率和持续时间作为该方法的参数,
- 播放多个声音(即同时播放三个声音,调用三个方法)。
在示例文件中看起来更复杂。当我想播放多个正弦波时,我必须合并所有这些波,然后将这些数据提供给流。
也许有人有更好的解决方案来解决这个问题?
我只是给你一个简单的例子(对于sine wave
),然后你可以创建你感兴趣的其他类型的波。需要的输入参数是
- sampling rate (e.g 8000, 16000 etc)
- amplitude (the actual values depend on the output format but it's best to have values in the range 0-1 and convert them to whatever format you like/need)
- frequency (expressed as a fraction of the sampling rate)
- duration (in seconds)
音调数据(样本)的缓冲区长度由 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
来存储样本。这样就不用担心内存了allocation/deallocation.
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_wave, https://en.wikipedia.org/wiki/Square_wave )
以上程序是一种快速生成音频的方法。 小更正: 而不是
const float freq = frequency/samplingRate;
应该是:
const float freq = frequency;
// 即。将频率直接传递到 sin()