NAudio fft结果给出所有频率C#的强度

我有一个工作实现NAudio的wasapi环回录制和数据的FFT。 我获得的大部分数据都是应该的,但每隔一段时间(10秒到几分钟的间隔),它几乎在所有频率上都显示振幅。

错误图片

基本上,图像从右到左滚动,时间和频率从底部的最低频率开始以对数标度进行。 这些线是错误。 据我所知,那些不应该在那里。

我得到音频缓冲区并将样本发送到聚合器(应用汉明窗口),该聚合器实现了NAudio FFT。 在我以任何方式修改它之前检查了数据(FFT结果)(图像不是来自原始FFT输出,而是desibel缩放),确认FFT结果给出了那些线。 我还可以指出图片是用LockBits修改的,所以我认为那里的逻辑有问题,但这就是我查看显示同样问题的FFT输出数据的原因。

好吧,我可能是错的,问题可能在某个地方,我说它不是,但它似乎真的来自FFT或缓冲数据(数据本身或样本的聚合)。 不知怎的,我怀疑缓冲区本身是否像这样被破坏了。

如果有人知道是什么原因造成这种情况我会非常感激!

UPDATE

所以我决定绘制整个FFT结果范围而不是它的一半。 它表现出奇怪的一些。 我不确定FFT,但我认为傅立叶变换应该给出一个围绕中间反映的结果。 这当然不是这种情况。

图像是线性比例的,因此图像的精确中间是FFT结果的中间点。 底部是第一个,顶部是最后一个。

wholefft

我正在播放一个10kHz的正弦波,它给出了两条水平线,但顶部超出了我。 看起来这些线条在图片的底部四分之一处被镜像,所以这对我来说也很奇怪。

更新2

所以我将FFT大小从4096增加到8192再次尝试。 这是我输出正弦频率的输出。

图片3

似乎结果反映了两次。 一旦在中间,然后再在上半部和下半部。 现在,巨大的线条已经消失了……看起来这些线条现在只出现在下半部分。

在使用不同的FFT长度进行一些进一步测试之后,该线路中的线条似乎是完全随机的。

更新3

我做过很多测试。 我添加的最新内容是样本重叠,以便在下一个FFT开始时重用示例数组的后半部分。 在汉明和汉恩的窗户上,它给了我很大的强度(就像我发布的第二张照片一样)但不是布莱克曼哈里斯。 禁用重叠可消除每个窗口函数上的最大错误。 即使使用BH窗口,顶部图片中的较小错误仍然存​​在。 我仍然不知道为什么会出现这些线条。

我当前的表单允许控制使用哪个窗口function(前面提到的三个),重叠(开/关)和多个不同的绘图选项。 这允许我在更改时比较所有影响方效果。

我会进一步调查(我很确定我在某些方面犯了一个错误)但是很好的建议非常受欢迎!

问题在于我处理数据数组的方式。 现在就像一个魅力。

代码(删除多余的,可能会增加错误):

// Other inputs are also usable. Just look through the NAudio library. private IWaveIn waveIn; private static int fftLength = 8192; // NAudio fft wants powers of two! // There might be a sample aggregator in NAudio somewhere but I made a variation for my needs private SampleAggregator sampleAggregator = new SampleAggregator(fftLength); public Main() { sampleAggregator.FftCalculated += new EventHandler(FftCalculated); sampleAggregator.PerformFFT = true; // Here you decide what you want to use as the waveIn. // There are many options in NAudio and you can use other streams/files. // Note that the code varies for each different source. waveIn = new WasapiLoopbackCapture(); waveIn.DataAvailable += OnDataAvailable; waveIn.StartRecording(); } void OnDataAvailable(object sender, WaveInEventArgs e) { if (this.InvokeRequired) { this.BeginInvoke(new EventHandler(OnDataAvailable), sender, e); } else { byte[] buffer = e.Buffer; int bytesRecorded = e.BytesRecorded; int bufferIncrement = waveIn.WaveFormat.BlockAlign; for (int index = 0; index < bytesRecorded; index += bufferIncrement) { float sample32 = BitConverter.ToSingle(buffer, index); sampleAggregator.Add(sample32); } } } void FftCalculated(object sender, FftEventArgs e) { // Do something with e.result! } 

和Sample Aggregator类:

 using NAudio.Dsp; // The Complex and FFT are here! class SampleAggregator { // FFT public event EventHandler FftCalculated; public bool PerformFFT { get; set; } // This Complex is NAudio's own! private Complex[] fftBuffer; private FftEventArgs fftArgs; private int fftPos; private int fftLength; private int m; public SampleAggregator(int fftLength) { if (!IsPowerOfTwo(fftLength)) { throw new ArgumentException("FFT Length must be a power of two"); } this.m = (int)Math.Log(fftLength, 2.0); this.fftLength = fftLength; this.fftBuffer = new Complex[fftLength]; this.fftArgs = new FftEventArgs(fftBuffer); } bool IsPowerOfTwo(int x) { return (x & (x - 1)) == 0; } public void Add(float value) { if (PerformFFT && FftCalculated != null) { // Remember the window function! There are many others as well. fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HammingWindow(fftPos, fftLength)); fftBuffer[fftPos].Y = 0; // This is always zero with audio. fftPos++; if (fftPos >= fftLength) { fftPos = 0; FastFourierTransform.FFT(true, m, fftBuffer); FftCalculated(this, fftArgs); } } } } public class FftEventArgs : EventArgs { [DebuggerStepThrough] public FftEventArgs(Complex[] result) { this.Result = result; } public Complex[] Result { get; private set; } } 

这就是我想的。 我可能错过了一些东西。 希望这可以帮助!