NAudio用于播放正弦波的算法,其频率可以实时平滑地改变

到目前为止,我已经实现了在这篇博客文章中找到的算法,但成效有限。

我的程序的概念是初始化正弦波,然后根据鼠标在屏幕上的位置改变频率 – 向上移动鼠标,正弦波变高,反之亦然(基本上是使用鼠标的一种类型仪器)。

到目前为止我所实现的问题是,当正弦波的频率更新时,会发出一声咔哒声,而不是提供平滑的频率扫描,使其听起来像是有离散的频率级别。 我一直在NAudio论坛和这里搜索高低,但似乎没有其他人尝试使用NAudio做这种事情,或者其他任何声音模块 – 所有执行的类似程序类似地使用像Kinect这样的设备使用虚拟midi布线和现有的软件模块,但我想在不依赖外部软件包的情况下实现相同的概念。

我已经在NAudio论坛上发布了有关此问题的代码部分,正如您所看到的,我正在通过MarkHeath的建议来尝试找到解决问题的方法。

您需要避免输出波形中的不连续性(这些是您听到的咔嗒声)。 最简单的方法是使用基于LUT的波形发生器 – 这适用于任何周期性波形(即不仅仅是纯正弦波)。 通常,您使用定点相位累加器,该累加器针对每个新样本递增一个与当前输出频率相对应的增量值。 您可以根据需要安全地修改delta,并且波形仍然是连续的。

伪代码(对于一个输出样本):

const int LUT_SIZE; const int LUT[LUT_SIZE]; // waveform lookup table (typically 2^N, N >= 8) Fixed index; // current index into LUT (integer + fraction) Fixed delta; // delta controls output frequency output_value = LUT[(int)index]; // NB: for higher quality use the fractional part of index to interpolate // between LUT[(int)index] and LUT[(int)index + 1], rather than just // truncating the index and using LUT[(int)index] only. Depends on both // LUT_SIZE and required output quality. index = (index + delta) % LUT_SIZE; 

注意:计算给定输出频率f和采样率Fs delta

 delta = FloatToFixed(LUT_SIZE * f / Fs);