如何用C语言进行声音合成



我正在使用ST板生成一个简单的乐器。基本上我有一个传感器,它可以检测运动或空间角度,并根据角度产生不同音高和音量的声音。我已经有了音频编解码器的驱动程序,所以我所需要做的就是生成声音样本并将样本提供给它。现在我可以从传感器中获得角度读数,但最具挑战性的部分是如何生成声音。从谷歌搜索到目前为止,我认为我需要生成一个sin函数,根据传感器的读数设置频率和振幅(体积)。但我的编解码器假设采样率为48KHz,那么我该如何在固定采样率下生成不同频率的正弦曲线呢?

到目前为止,我已经这样做了:

samplingRate = 48000;
n = 0;  // reset once there is a change in frequency
// this function is called 48000 times a second
int generateSineWave(float frequency, float volume)
{
int temp = volume*(sin(2*pi*frequency*n);
n = n + 1; 
if (n == samplingRate) {
n = 0;
}
if (abs(temp) > MAXVAL) {
return ERROR_CODE;
}
return temp;
}

这似乎是有效的(我听到了一些东西),但我不确定它是否产生了正确的频率正弦曲线。我听到的声音也不是很悦耳,我该如何产生复杂的音调(比如钢琴上的音调)?我想我的控制变量(空间角度)也需要低通滤波。但除此之外,还有什么关于我如何产生更令人愉快的海浪的想法吗?

由于采样频率为48 kHz(每秒48000个样本),因此1 Hz正弦曲线需要一秒钟或48000个采样才能完成一个循环。因此,您需要归一化,或除以采样率:

temp = volume * sin(2 * pi * n * frequency / samplingRate);

请注意,temp必须始终在-volumevolume的范围内,因此您只需要检查一次volume < MAXVAL,并且可以在计算temp之前进行检查,这将更有效地检测错误(非常轻微)。您会发现pi已经在math.h中定义为M_PI

你提到的音调不是很悦耳。这是一个可能出了问题的迹象,因为纯净的正弦曲线听起来很纯净,而且通常很令人愉快。你可能会尝试一件简单的事情,就是在过零点处开始和停止你的音调;否则,您将在过渡处听到咔嗒声或失真声。或者,可以通过乘以"渐变"函数来淡入和淡出它们,可以通过在短时间内将float从1减至0来创建该函数。

一些C语言提示:

&公牛;您可以将n = n + 1替换为++n

&公牛;您可以更换

if (abs(temp) > MAXVAL) {
return ERROR_CODE;
}
return temp;

带有

return abs(temp) > MAXVAL ? ERROR_CODE : temp;

&公牛;如果您选择保留if,那么即使是单行体也要使用大括号,因为有一天您可能会添加另一行,而忘记大括号。这是一个特别难找到的错误,因为你会按照预期的方式阅读代码,而不是按照实际情况阅读。请相信我。:-)

最新更新