我想在我的音频生成器应用程序中找出一些生成振荡器波形的代码。这个例子中的一个是正弦波,有人可以告诉我代码是如何工作的,因为我希望将来制作自定义波形类型和方形,锯齿形和三角形类型。
OSStatus RenderTone(
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
// Fixed amplitude is good enough for our purposes
const double amplitude = 0.25;
// Get the tone parameters out of the view controller
ToneGeneratorViewController *viewController =
(ToneGeneratorViewController *)inRefCon;
double theta = viewController->theta;
double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
// This is a mono tone generator so we only need the first buffer
const int channel = 0;
Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;
// Generate the samples
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buffer[frame] = sin(theta) * amplitude;
theta += theta_increment;
if (theta > 2.0 * M_PI)
{
theta -= 2.0 * M_PI;
}
}
// Store the theta back in the view controller
viewController->theta = theta;
return noErr;
}
答案 0 :(得分:1)
正在生成实际的正弦波样本,并在下面的代码段中填充缓冲区
for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
buffer[frame] = sin(theta) * amplitude;
theta += theta_increment;
if (theta > 2.0 * M_PI)
{
theta -= 2.0 * M_PI;
}
}
在分配buffer[frame]
的行中,您正在调用sin(theta) * amplitude
,并且对于for
循环的每次迭代,您通过某个有限步骤递增theta
大小取决于您的频率和采样率,通过
double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
基本上将2.0 * PI * frequency
除以您的采样率。
在循环theta
循环时递增for
变量基本上是一次一个样本的时间步长,直到缓冲区已满(即frame == iNumberFrames
)。
如果您想要生成除正弦波以外的其他内容,您只需使用其他功能替换以下行:
buffer[frame] = sin(theta) * amplitude;
即。比方说,你想要无限傅立叶级数中的前三个项收敛为三角波;你可能会有以下代码......
buffer[frame] = (8 / pow(M_PI,2)) * (sin(theta) - sin(3*theta)/9 + sin(5*theta)/25);
答案 1 :(得分:1)
要生成所需的波形,您需要将sin()函数替换为产生所需波形的函数。
您可以在带有图形示例的函数表中找到此函数,或者您可能必须创建函数。有很多方法可以创建一个函数逼近,包括多项式,傅里叶级数,有或没有插值的表查找,递归等等。但这本身就是一个很大的主题(许多教科书等)