我正在使用 ST 板生成一个简单的乐器。基本上,我有一个传感器可以检测运动或空间角度,并根据角度生成不同音高和音量的声音。我已经有了音频编解码器的驱动程序,所以我需要做的就是生成声音样本并将样本提供给它。现在我能够从传感器获得角度读数,但具有挑战性的部分是如何产生声音。从谷歌搜索到目前为止,我想我需要根据传感器的读数生成一个频率和振幅(音量)设置的 sin 函数。但是我的编解码器假定采样率为 0f 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(每秒 48,000 个样本)进行采样,因此 1 Hz 正弦波完成一个周期需要一秒或 48,000 个样本。因此,您需要按采样率归一化或除以:
temp = volume * sin(2 * pi * n * frequency / samplingRate);
请注意 temp
必须始终在 -volume
的范围内至 volume
, 所以你只需要检查一次 volume < MAXVAL
,您可以在计算 temp
之前执行此操作,这将更有效地检测错误(非常轻微)。你会发现 pi
已经为您定义为 M_PI
在 math.h
.
您提到音调不是很悦耳。这表明可能存在问题,因为纯正弦波听起来非常纯净,而且总体上令人愉悦。您可能会尝试的一件简单的事情就是在零交叉处开始和停止您的音调;否则你会在转换时听到咔哒声或失真。或者,您可以通过乘以“斜坡”函数来使它们淡入淡出,您可以通过减少 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
,即使对于单行主体也使用大括号是个好主意,因为有一天您可能会添加另一行而忘记大括号。这是一个特别难发现的错误,因为您将按照您期望的方式阅读代码,而不是实际的样子。相信我。 :-)
关于c - 如何在C中进行声音合成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13436319/