初学者尝试使用 Numpy 进行 FFT 信号滤波

信息处理 fft 过滤器 Python 快速卷积
2021-12-27 04:49:20

我试过四处寻找有关这方面的信息,但我真的不适合这里。我是一个喜欢玩 Python 的人,我想制作一个过滤音频文件的程序。我正在使用 Python 和 NumPy,以及用于导入和导出 Wave 文件的 scipy.io.wavfile 模块。我已经弄乱了音量,但没有过滤。这是我到目前为止所拥有的。

rate, data = wavfile.read('./TriLeftChannel.wav') 

filtereddata = numpy.fft.rfft(data) # FFT Filtered data
freqdata = numpy.fft.fftfreq(data.size) #Frequency data
filtereddata = AudioFunctions.Filter(filtereddata, freqdata, data, rate) # Filter the data

def Filter(filtereddata, freqdata, data, rate):

    #fftchunks = (rate / 2)# + 1

    x = freqdata[:len(data) / 2]

    for f in range(len(x)):

        if x[f] > 0.1:
            filtereddata[f] = 0.0
            filtereddata[len(data) / 2 + f] = 0.0       

    return filtereddata

在该函数中,filtereddata 是 FFT 数据,freqdata 是我使用 fftfreq() 获得的频率数据,data 是波形文件本身,“裸”。速率是采样率(虽然我不使用它)。这个函数实际上并没有过滤频率(虽然我知道它是一个硬滤波器,没有滤波器真的应该这么苛刻)。完成后,我输出文件

filteredwrite = numpy.fft.irfft(filtereddata)

filteredwrite = numpy.round(filteredwrite).astype('int16') # Round off the numbers, and get ready to save it as 16-bit depth file (?)

wavfile.write('TestFiltered.wav', rate, filteredwrite)

由于即使走到这一步我也有点挣扎,我想知道是否有人可以给我任何指示或 FFT 的初学者教程?当然,任何帮助将不胜感激。

编辑:修复了缩进问题。

3个回答

您的方法存在两个潜在问题:

  • 您正在计算整个信号的 FFT,如果您的输入数据变得太大,这将非常低效,并且会阻止您使用窗口化。如果您想对信号进行频域修改,请考虑使用短期傅里叶变换,处理生成的 FFT 帧,并使用重叠相加重新合成时域信号。
  • FFT -> 将 FFT 系数归零 -> IFFT,尤其是在没有输入数据窗口的情况下,很少用于滤波,因为它会产生具有许多不需要的特性(旁瓣 + 非因果)的滤波器。

您的代码中的一个潜在问题:

我不明白你为什么将filtereddata[len(data) / 2 + f]系数归零。我假设它打算将“负频率”归零,但是数组索引是错误的,并且您使用numpy.fft.rfft的输出布局与numpy.fft.fft(不返回负频率的 FFT 系数)不同。我很惊讶这个运行,你的代码实际上应该导致索引越界错误。

我的建议是让您了解 FIR / IIR 滤波器,设计一个适合您的约束条件的滤波器,并将其应用于您的数据。在 FIR / IIR 滤波器及其设计方面有一套完善的工作、软件工具和实践。一旦有了系数,对于小序列和/或如果复杂性不是问题,就scipy.signal.lfilter可以完成这项工作。正如 Jason R 所建议的,使用 FFT + 重叠相加可以使应用长 FIR 在计算上变得非常高效。

我很高兴实施这个人所说的:

http://mpastell.com/2010/01/18/fir-with-scipy/

我使用的典型低通滤波器来自给定的链接,是这样的:

def firfilt(interval, freq, sampling_rate):
    nfreq = freq/(0.5*sampling_rate)
    taps =  sampling_rate + 1
    a = 1
    b = scipy.signal.firwin(taps, cutoff=nfreq)
    return scipy.signal.lfilter(b, a, interval)

线性 FIR 滤波器使用离散卷积应用于信号(如您的音频文件)使用 FFT 可以有效地实现卷积。执行此操作的两个单独方案称为重叠保存重叠添加方法。我个人更喜欢重叠保存,因为它实现起来更简单。从你的问题中不清楚你到底挂断了什么。您应该拥有所有带有 NumPy 的高级工具,这些工具可以让您轻松地将 OLS 或 OLA 算法组合在一起。

虽然这些技术非常简单,但尝试对幕后发生的事情以及它们为什么起作用有一个基本的了解是值得的。对于一本好的 DSP 入门书,我会推荐Lyons 的 DSP 书或者,有一本名​​为“数字信号处理的科学家和工程师指南”的在线书籍,我听说过很好的东西(你无法击败价格)。