如何在 C 中进行声音合成?
Posted
技术标签:
【中文标题】如何在 C 中进行声音合成?【英文标题】:How to perform sound synthesis in C? 【发布时间】:2012-11-18 00:35:21 【问题描述】:我正在使用 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;
这似乎有效(我听到了一些声音),但我不确定它是否生成了正确的频率正弦波。我听到的声音也不是很悦耳,我将如何产生复杂的音调(例如钢琴中的音调)?我想我的控制变量(空间角度)也需要低通滤波。但除此之外,还有什么想法可以让我产生更悦耳的声波吗?
【问题讨论】:
如果你想学习计算机音乐合成,一个很好的资源是Stanford's Center for Computer Research in Music and Acoustics。许多关于几乎所有合成方法的出版物——采样、加法、减法、FM、PM(Karplus-Strong 等)——以及关于如何在现实硬件上实现算法的论文,以及指向软件包的链接实现算法。 【参考方案1】:由于您以 48 kHz(每秒 48,000 个样本)进行采样,因此 1 Hz 正弦波完成一个周期需要一秒或 48,000 个样本。所以你需要标准化,或者除以采样率:
temp = volume * sin(2 * pi * n * frequency / samplingRate);
注意temp
必须始终在-volume
到volume
的范围内,因此您只需检查一次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
,即使是单行正文也最好使用大括号,因为您可能有一天会添加另一行而忘记大括号。这是一个特别难以发现的错误,因为您会按照 预期 的方式阅读代码,而不是按实际情况阅读。相信我。 :-)
【讨论】:
感谢您的提示!我同意我有点草率。以上是关于如何在 C 中进行声音合成?的主要内容,如果未能解决你的问题,请参考以下文章