1

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

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

4

1 回答 1

5

由于您以 48 kHz(每秒 48,000 个样本)进行采样,因此 1 Hz 正弦波完成一个周期需要一秒或 48,000 个样本。因此,您需要按采样率对 进行归一化或除法:

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

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

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

一些C语言技巧:

• 您可以替换n = n + 1++n

• 您可以更换

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

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

• 如果您选择保留if,最好对单行正文使用大括号,因为有一天您可能会添加另一行而忘记大括号。这是一个特别难以找到的错误,因为您会按照您的预期阅读代码,而不是实际阅读代码。相信我。:-)

于 2012-11-18T00:46:07.393 回答