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



到目前为止,我已经实现了这篇博客文章中发现的算法,但收效甚微。

我的程序的概念是初始化正弦波,然后根据鼠标在屏幕上的位置改变频率-将鼠标向上移动,正弦波变得更高,反之亦然(本质上是使用鼠标的特雷门式仪器)。

到目前为止,我所实现的问题是,当正弦波的频率更新时,有一个可听到的咔哒声,而不是提供平滑的频率扫描,使它听起来像有离散的频率水平。我一直在NAudio论坛和这里四处搜索,但似乎没有其他人试图使用NAudio或任何其他声音模块来做这种事情-所有类似的程序都使用类似的设备,如Kinect使用虚拟midi电缆和现有的软件模块,但我想实现相同的概念,而不依赖于外部软件包。

我已经在NAudio的论坛上发布了关于这个问题的代码部分,正如你所看到的,我正在遵循MarkHeath在这里的建议,试图找到解决我问题的方法。

您需要避免输出波形中的不连续(这些是您听到的点击声)。最简单的方法是使用基于lut的波形发生器-这适用于任何周期波形(即不仅仅是纯正弦波)。通常你使用一个固定点相位累加器,每个新样本增加一个delta值,对应于当前输出频率。你可以安全地修改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);

最新更新