简体   繁体   English

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

[英]NAudio fft result gives intensity on all frequencies C#

I have a working implementation of NAudio's wasapi loopback recording and the FFT of the data. 我有一个工作实现NAudio的wasapi环回录制和数据的FFT。 Most of the data I get is just as it should be but every once in a while (10 sec to minutes intervals) it shows amplitude on almost all frequencies. 我获得的大部分数据都是应该的,但是每隔一段时间(10秒到几分钟的间隔),它几乎在所有频率上显示振幅。

错误图片

Basicly the picture is rolling from right to left with time and frequencies going on logarithmic scale from lowest frequencies on the bottom. 基本上,图像从右到左滚动,时间和频率从底部的最低频率开始以对数标度进行。 The lines are the errors. 这些线是错误。 As far as i can tell those are not supposed to be there. 据我所知,那些不应该在那里。

I get the audio buffer and send the samples to an aggregator (applies Hamming window) which implements the NAudio FFT. 我得到音频缓冲区并将样本发送到聚合器(应用汉明窗口),该聚合器实现了NAudio FFT。 I have checked the data (FFT result) before I modify it in any way (the picture is not from the raw FFT output, but desibel scaled) confirming the FFT result is giving those lines. 在我以任何方式修改它之前检查了数据(FFT结果)(图像不是来自原始FFT输出,而是desibel缩放),确认FFT结果给出了那些线。 I could also point out the picture is modified with LockBits so I thought I had something wrong with the logic there, but that's why I checked the FFT output data which shows the same problem. 我还可以指出图片是用LockBits修改的,所以我认为那里的逻辑有问题,但这就是为什么我检查了显示相同问题的FFT输出数据。

Well I could be wrong and the problem might be somewhere I said it isn't but it really seems it originates from the FFT OR the buffer data (data itself or the aggregation of samples). 好吧,我可能是错的,问题可能在某个地方,我说它不是,但它似乎真的来自FFT或缓冲数据(数据本身或样本的聚合)。 Somehow I doubt the buffer itself is corrupted like this. 不知怎的,我怀疑缓冲区本身是否像这样被破坏了。

If anyone has any idea what could cause this I would greatly appreciate it! 如果有人知道可能导致这种情况的话,我会非常感激!

UPDATE UPDATE

So I decided to draw the whole FFT result range rather than half of it. 所以我决定绘制整个FFT结果范围而不是它的一半。 It showed something strange. 它表现出一些奇怪的。 I'm not sure of FFT but I thought Fourier transformation should give a result that is mirrored around the middle. 我不确定FFT,但我认为傅里叶变换应该给出一个反映在中间的结果。 This certainly is not the case here. 这当然不是这种情况。

The picture is in linear scale so the exact middle of the picture is the middle point of the FFT result. 图像是线性比例的,因此图像的中间位置是FFT结果的中间点。 Bottom is the first and top is the last. 底部是第一个,顶部是最后一个。

wholefft

I was playing a 10kHz sine wave which gives the two horizontal lines there but the top part is beyond me. 我正在播放一个10kHz的正弦波,它给出了两条水平线,但顶部超出了我的范围。 It also seems like the lines are mirrored around the bottom quarter of the picture so that seems strange to me as well. 看起来这些线条在图片的底部四分之一处被镜像,所以这对我来说也很奇怪。

UPDATE 2 更新2

So I increased the FFT size from 4096 to 8192 and tried again. 所以我将FFT大小从4096增加到8192再次尝试。 This is the output with me messing with the sine frequency. 这是我输出正弦频率的输出。

图片3

It would seem the result is mirrored twice. 似乎结果反映了两次。 Once in the middle and then again on the top and bottom halves. 一旦在中间,然后再在上半部和下半部。 And the huge lines are now gone.. And it would seem like the lines only appear on the bottom half now. 巨大的线条现在已经消失了......看起来这些线条现在只出现在下半部分了。

After some further testing with different FFT lengths it seems the lines are completely random in that account. 在使用不同的FFT长度进行一些进一步测试之后,该线路中的线条似乎是完全随机的。

UPDATE 3 更新3

I have done some testing with many things. 我做了很多测试。 The latest thing I added was overlapping of samples so that I reuse the last half of the sample array in the beginning of the next FFT. 我添加的最新内容是样本重叠,以便在下一个FFT开始时重用示例数组的后半部分。 On Hamming and Hann windows it gives me massive intensities (quite like in the second picture I posted) but not with BlackmannHarris. 在汉明和汉恩的窗户上,它给了我很大的强度(就像我发布的第二张照片一样)但不是布莱克曼哈里斯。 Disabling overlapping removes the biggest errors on every window function. 禁用重叠会删除每个窗口函数上的最大错误。 The smaller errors like in the top picture still remain even with BH window. 即使使用BH窗口,顶部图片中的较小错误仍然存​​在。 I still have no idea why those lines appear. 我仍然不知道为什么会出现这些线条。

My current form allows control over which window function to use (of the three previously mentioned), overlapping (on/off) and multiple different drawing options. 我当前的表单允许控制使用哪个窗口功能(前面提到的三个),重叠(开/关)和多个不同的绘图选项。 This allows me to compare all the affecting parties effects when changed. 这允许我在更改时比较所有影响方效果。

I shall investigate further (I am quite sure I have made a mistake at some point) but good suggestions are more than welcome! 我会进一步调查(我很确定我在某些方面犯了一个错误)但是很好的建议非常受欢迎!

The problem was in the way I handled the data arrays. 问题在于我处理数据数组的方式。 Working like a charm now. 现在就像一个魅力。

Code (removed excess and might have added mistakes): 代码(删除多余的,可能会增加错误):

// 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<FftEventArgs>(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<WaveInEventArgs>(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!
}

And the Sample Aggregator class: 和Sample Aggregator类:

using NAudio.Dsp; // The Complex and FFT are here!

class SampleAggregator
{
    // FFT
    public event EventHandler<FftEventArgs> 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; }
}

And that is it I think. 这就是我想的。 I might have missed something though. 我可能错过了一些东西。 Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM