C# 在音频上使用低通滤波器

C# 在音频上使用低通滤波器,c#,audio,fft,naudio,lowpass-filter,C#,Audio,Fft,Naudio,Lowpass Filter,我是DSP和滤波领域的新手。就像我一周前开始的那样。不管怎样,我一直在寻找方法,对我得到的一些数据使用滤波器(低通、高通、陷波等)。数据以双倍数组的形式出现,在这个数组中我可以得到100多万个点。我试图过滤掉给定某个截止频率的声音,但无法让任何算法工作。我在互联网上走来走去,尝试了许多不同的库和方法,但没有得到任何结果。我偏爱NAudio库,因为它似乎拥有我所需要的一切(FFT和BiQuadFilter类的滤波)。我敢肯定,我的问题是我极度缺乏获得所需输出的知识和数学。从我读到的内容来看,我认为

我是DSP和滤波领域的新手。就像我一周前开始的那样。不管怎样,我一直在寻找方法,对我得到的一些数据使用滤波器(低通、高通、陷波等)。数据以双倍数组的形式出现,在这个数组中我可以得到100多万个点。我试图过滤掉给定某个截止频率的声音,但无法让任何算法工作。我在互联网上走来走去,尝试了许多不同的库和方法,但没有得到任何结果。我偏爱NAudio库,因为它似乎拥有我所需要的一切(FFT和BiQuadFilter类的滤波)。我敢肯定,我的问题是我极度缺乏获得所需输出的知识和数学。从我读到的内容来看,我认为这个过程应该是这样的:

  • 将数据插入FFT,将数据放入频域
  • 将结果数据传递到过滤器(低、高、陷波)
  • 从步骤2中的结果执行IFFT以返回时域
  • 播放声音
  • 这是过滤音频的正确方法吗?我可以把整个数组塞进FFT,还是必须把它分成小块?我如何处理FFT结果中得到的复数(即仅使用实部而不使用虚部,或使用幅值和相位)?我真的不知道什么是“正确的方法”

    编辑

    我终于成功了!以下是我所做的:

            byte[] data = doubleArray.SelectMany(value => BitConverter.GetBytes(value)).ToArray();
            wms = new WaveMemoryStream(data, sampleRate, (ushort)audioBitsPerSample, (ushort)channels);
            WaveFileReader wfr = new WaveFileReader(wms);
            SampleChannel sample = new SampleChannel(wfr, false);
            LowPassSampleProvider sampleProvider = new LowPassSampleProvider(sample);
            WaveOutEvent player = new WaveOutEvent();
            player.Init(sampleProvider);
            player.Play();
    
    doubleArray
    是我的加速计数据数组,目前它包含100万个点,每个点大约1.84

    WaveMemoryStream
    是我发现的一个类


    LowPassSampleProvider
    是我制作的一个类,它实现了ISampleProvider,并将样本传递给BiQuadFilter.LowPassFilter函数。

    通常,您会通过时域过滤器运行时域数据。另一种方法是等效的,即取数据的FFT和滤波器的FFT,在频域中相乘,然后取逆FFT。对于小型滤波器,时域方法通常更快。您通常会在数据帧上执行此操作,例如通过过滤器的8192个样本。然后对后续帧重复此操作。如果不看你的代码,我无法提供更多的帮助。另外,请使用Intel的IPP查看这些。有时域和频域两种实现方式可以帮助您进行操作。

    NAudio中的
    BiQuadFilter
    在时域中运行。您不需要对其使用FFT。将每个样本传递到
    Transform
    方法中,以获得输出样本。如果您有立体声音频,请使用两个过滤器,一个用于左侧,一个用于右侧


    我通常制作一个
    ISampleProvider
    实现,在Read方法中从源
    ISampleProvider
    (例如
    AudioFileReader
    )读取,并通过过滤器传递示例。

    我编辑了您的标题。请看“,”其中的共识是“不,他们不应该”。这个答案是正确的。如果你发现用时域而不是频域来改变信号的频率是违反直觉的,我确实为此写了一篇博文:谢谢你的提示,但我似乎仍然无法让它工作。你能看看我在OP上做的编辑,看看我做错了什么吗?那里有很多转换。你的信号链应该是A->B->C,其中A是一个样本提供者,返回你想在其读取方法中处理的样本,B是一个样本提供者,在读取时通过样本传递音频,C是你的接收器(WaveOutEvent或WaveFileWriter)。并非所有的时域滤波器都被正确理解为卷积。例如,IIR滤波器(在音频中最常见),虽然可以用长卷积近似,但并不等同于卷积。@AndrewFernandes这些英特尔IPP示例不再可用。你能提供另一个来源或上传到某个地方吗?这将非常有用。@Lati示例可用,您只需通过谷歌搜索“英特尔IPP示例”。