如何进行声音合成?

信息处理 声音的 声音
2022-02-05 13:56:05

我正在使用 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;
}

这似乎有效(我听到了一些声音),但我不确定它是否产生了正确的频率正弦曲线。我听到的声音也不是很悦耳,我将如何产生复杂的音调(例如钢琴中的音调)?我想我的控制变量(空间角度)也需要低通滤波。但除此之外,关于如何产生更悦耳的波浪的任何想法?

我是声音合成的新手,所以任何建议/帮助将不胜感激。

1个回答

首先,您对正弦波的计算有问题。它应该是这样的:

音量 * sin(2 * pi * 频率 * n / SAMPLE_RATE);

目前,您的代码正在生成非常高的频率,而您听到的是它们的镜像。

这是首先要解决的问题。您的代码中的其他问题包括:

  • 每次更改频率时都重置变量 n - 这会在波形中产生不连续性(“咔哒声”)。
  • 每次达到采样率时重置变量 n。您不确定波形是否已完成一系列完整周期,因为频率可能不是整数。
  • 通过乘法而不是通过频率积分直接计算相位。在调制频率时会引起问题
  • 直接计算 sin 函数,这在嵌入式硬件上是一项昂贵的操作,必须用表查找 + 插值代替。

此外,请确保您的样本相对于 DAC 的比例进行了适当的缩放(例如,如果将其发送到带有无符号代码的 12 位 DAC,则音量必须小于 2047,并且您应该添加 2048 偏移量)。

如果你让它工作,你会得到一个纯净的音调——我不会称这种音调“不愉快”,但它是静态的,不会让人联想到任何乐器。

有许多声音合成技术可供尝试,本文不对其进行概述。简而言之:

  • 减法合成的工作原理是使用简单波形(锯齿波、方波)生成谐波丰富的音调,然后通过滤波器对其进行整形。它不是很擅长产生“逼真”的声音,但它实现起来相对容易(最棘手的步骤是带限波形生成,请阅读 minBLEP),它产生的声音具有表现力,并且很容易理解每​​个合成参数如何涉及到声音的各个方面。由 65-85 中的合成器使用,由于它们在电子/舞曲中产生的声音的流行,自 95 年起复兴使减法合成听起来更逼真的一种“作弊”方法是使用真实乐器的单周期波形代替振荡器,这种技术称为波表合成。
  • 加法合成通过对不同频率/幅度的正弦部分求和来直接构建复杂的音调。考虑到所涉及的部分数量及其随时间变化的复杂性,这是一种相当不切实际的方法。
  • FM 合成通过互连简单的正弦波振荡器来工作,这些振荡器相互调制频率。它非常擅长模仿自然声音(尤其是铜管乐器、金属乐器),但很难理解它的参数(频率比和调制指数)与有意义的音乐参数(例如声音“亮度”)之间的关系。八十年代有过一个黄金时代,然后逐渐淡出。
  • 采样使用真实乐器的录音,并调整录音(又名样本)的播放速度以模拟不同的音符。使用这种方法,可以轻松获得可以立即识别为钢琴或吉他或咳嗽的 Ferris Bueller的东西- 但如果您希望捕捉乐器的所有演奏细微差别,您将需要越来越多的录音。目前在许多应用中声音合成的主要形式,由最低的数据存储成本驱动。
  • 物理建模尝试使用有限元模型或数字波导等技术来模拟乐器中发生的物理过程。这个过程在计算上可能很昂贵和/或需要复杂的建模和数据分析工作。结果在再现乐器的所有演奏细微差别方面非常具有表现力。目前相当少见,除了一些非常狭窄的应用(钢琴合成)。

真的是“写实/表现/简约,二选一”的案例。

我不确定你的目标——你的系统应该提供多少乐器声音?除了音高和音量之外,您还想用加速度计数据调制其他声音参数吗?我也不确定您的目标平台(ST MCU 从 24 MHz/32kb 闪存/无 FPU 到具有 FPU 和 DSP 指令以及 1M 板载闪存的 168 MHz)。另一个要考虑的因素是复音 - 您是否希望您的系统能够同时演奏多个音符?

我会推荐:

  • 如果您有至少 128kb 的闪存并且只需要一个声音/乐器,或者如果您的 CPU 非常有限,则进行采样。
  • 如果您的闪光灯较少和/或需要更多声音/乐器,则减法合成;或者如果您需要使用外部传感器数据来轻松调制除音高/音量之外的声音参数。