我在一周前开始玩PortAudio库。我检查了大部分教程/测试示例,但没有看到我需要的解决方案。我正在制作简单的音序器 - 我已经在钢琴卷上做了绘画声音作为块,但现在我需要以某种方式使它听起来。我想知道是否有可能让它像这样工作:
在示例文件中,它看起来更复杂。当我想播放多个正弦波时,我必须合并所有波形,然后将数据提供给流。
也许有人有更好的解决方案来解决这个问题?
答案 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_wave,https://en.wikipedia.org/wiki/Square_wave)
答案 1 :(得分:0)
以上程序是生成音频的一种快速方法。 小修正: 代替
const float freq = frequency/samplingRate;
应为:
const float freq = frequency;
//即将频率直接传递到sin()