如何使用NAudio实时计算FFT(ASIO输出)

我正在编写吉他(小提琴)英雄的克隆作为本学年的最终项目。

我的想法是从我的电子小提琴中获取输入,通过FFT进行分析,做一些逻辑并绘制并通过扬声器输出。 也许是并行线程中的一些步骤。

我已经实现了Asio低延迟输入输出,但我在实现实时FFT时遇到了很大的问题。

这是一个与sampleAggregator一起设置asioOut的代码。 样本聚合器应存储每次调用AudioAvailable()时添加的样本,并在样本数超过fftLength时触发FFT计算。

private static int fftLength = 8192; private SampleAggregator sampleAggregator = new SampleAggregator(fftLength); void asioStartPlaying(object sender, EventArgs e) { sampleAggregator.PerformFFT = true; sampleAggregator.FftCalculated += new EventHandler(FftCalculated); var asioOut = new AsioOut(); BufferedWaveProvider wavprov = new BufferedWaveProvider(new WaveFormat(48000, 1)); asioOut.AudioAvailable += new EventHandler (asio_DataAvailable); asioOut.InitRecordAndPlayback(wavprov, 1, 25); asioOut.Play(); } void asio_DataAvailable(object sender, AsioAudioAvailableEventArgs e) { byte[] buf = new byte[e.SamplesPerBuffer*4]; for (int i = 0; i < e.InputBuffers.Length; i++) { Marshal.Copy(e.InputBuffers[i], buf, 0, e.SamplesPerBuffer*4); Marshal.Copy(buf, 0, e.OutputBuffers[i], e.SamplesPerBuffer*4); } for (int i = 0; i < buf.Length; i=i+4) { float sample32 = BitConverter.ToSingle(buf, i); sampleAggregator.Add(sample32); } e.WrittenToOutputBuffers = true; } 

SampleAggregator是取自NAudio fft的类, 结果给出所有频率C#的强度 。

Asio以Int32LSB样本类型输出数据。 在buf中,值为0到255。

这是在计算fft时调用的函数(从SampleAggregator类触发)。

 void FftCalculated(object sender, FftEventArgs e) { for (var i = 0; i < e.Result.Length; i++) { Debug.WriteLine("FFT output."); Debug.WriteLine(e.Result[i].X); Debug.WriteLine(e.Result[i].Y); } } 

但FFT总是输出NaN。

我认为转换为float存在问题。

有人能指出我正确的方向吗?

EDIT_1:我将DataAvailable()中的循环更改为

 for (int i = 0; i < e.SamplesPerBuffer * 4; i++) { float sample32 = Convert.ToSingle(buf[i]); sampleAggregator.Add(sample32); } 

FFT现在输出数据。 但我认为他们不正确。 错误必须在asio样本和浮点值之间的转换中。 但我对字节操作不太满意。

e.GetAsInterleavedSamples能以某种方式提供帮助吗?

来自FFT的原始数据样本:X:-5,304741 Y:-0,7160959 X:6,270798 Y:-0,4169312 X:-8,851931 Y:-0,4485725

我注意到,来自FFT的原始数据中的前几个和最后几个值在某种程度上比其他数据大。 使计算量级变得棘手。

问题是我想在转换来自Asio的样本数据(buf数组中连续4个字节)到fft浮动时。 BitConvertor应该做的伎俩,但它在某种程度上使fft输出NaN在我的情况下。 所以我尝试了这种转换。

 for (int i = 0; i < e.SamplesPerBuffer * 4; i=i+4) { float sample = Convert.ToSingle(buf[i] + buf[i+1] + buf[i+2] + buf[i+3]); sampleAggregator.Add(sample); } 

而且效果很好。 即使采样率为192 000。

我没有使用过NAudio,但是我们用DirectSound实现了非常类似的东西。 LightningChart Ultimate SDK中有这方面的工具。 AudioInput组件从声音设备捕获波形数据,数据同时转发到FFT计算(SpectrumCalculator组件)和波形监视器。 然后将FFT数据可视化为2D或3D中的谱图。 AudioOutput将数据写入声音设备,以通过扬声器发出声音。

总的来说,音频输入/输出,FFT计算和可视化以非常低的CPU负载运行。

LightningChart演示应用程序中的频谱图示例

我们的库是商业的,但我认为即使您没有寻找任何其他组件,最好看一下我们的音频示例,源代码在演示应用程序Visual Studio项目中可见。 你可能会得到新的想法,至少:-)你相信,你可以为NAudio应用一些方法。

从LightningChart网站下载LightningChart演示,运行它不需要任何费用。

[我是LightningChart组件的首席技术官]