PortAudio:通过调用函数播放多个生成的声音
Posted
技术标签:
【中文标题】PortAudio:通过调用函数播放多个生成的声音【英文标题】:PortAudio: Play multiple generated sounds by calling function 【发布时间】:2017-12-10 15:17:59 【问题描述】:大约一周前,我开始使用 PortAudio 库。我已经检查了大多数教程/测试示例,但还没有看到我需要的解决方案。我正在制作简单的音序器——我已经在钢琴卷轴上绘制了声音块,但现在我需要以某种方式让它听起来。我想知道是否有可能让它像这样工作:
运行一个播放一个声音的方法, 将声音的频率和持续时间作为该方法的参数, 播放多个声音(即同时三个声音,调用三个方法)。在示例文件中,它看起来更复杂。当我想播放多个正弦波时,我必须合并所有这些波,然后将这些数据提供给流式传输。
也许有人有更好的解决方案来解决这个问题?
【问题讨论】:
大多数音频设备不支持同时播放多个文件,因此您必须创建一个简单的混音器才能做到这一点。只要您的文件具有相同的采样率,这相当简单。即使您没有指定它,您似乎也想创建一个音调发生器。同样,网上有很多资源,请查看它们。不熟悉 PortAudio 是否支持其中任何一个。 是的,我想创建音调发生器,它将产生正弦波、方波、三角波和锯齿波。我不知道如何用用户定义的频率制作这些波,并同时播放很多声音。 到目前为止您尝试过什么?创建一个简单的音源应用程序并不难。 我有类似这个例子的东西。已经做了一些研究并且知道如何改变频率和多种音调,但仍然试图让它像我上面发布的那样。 (这里是生成正弦波示例的链接:link) PortAudio 无法为您提供帮助,但我可以编写一个简单的 C++ 函数来生成正弦波并接受频率和持续时间作为参数。这样,您将能够理解的不仅仅是使用库(尽管我并不是说使用库有什么问题) 【参考方案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)
【讨论】:
【参考方案2】:上述程序是一种快速生成音频的方法。 小修正: 而不是
const float freq = frequency/samplingRate;
应该是:
const float freq = frequency;
// 即。将频率直接传递到 sin()
【讨论】:
以上是关于PortAudio:通过调用函数播放多个生成的声音的主要内容,如果未能解决你的问题,请参考以下文章