Python 在连续时间帧上应用IIR滤波器时的连续性问题

Python 在连续时间帧上应用IIR滤波器时的连续性问题,python,numpy,audio,scipy,signal-processing,Python,Numpy,Audio,Scipy,Signal Processing,我想在每个1024个样本的连续块/时间帧上应用FIR或IIR滤波器(例如:低通滤波器) 可能的应用: 实时音频处理,如EQing。在一个精确的时间,我们在一个缓冲区中只有接下来的1024个样本。下一个要处理的样本尚不可用(实时) 按照建议,通过将输入信号分块来制作截止时变滤波器 我在这里试过: import numpy as np from scipy.io import wavfile from scipy.signal import butter, lfilter, filtfilt

我想在每个1024个样本的连续块/时间帧上应用FIR或IIR滤波器(例如:低通滤波器)

可能的应用:

  • 实时音频处理,如EQing。在一个精确的时间,我们在一个缓冲区中只有接下来的1024个样本。下一个要处理的样本尚不可用(实时)

  • 按照建议,通过将输入信号分块来制作截止时变滤波器

我在这里试过:

import numpy as np
from scipy.io import wavfile
from scipy.signal import butter, lfilter, filtfilt, firwin

sr, x = wavfile.read('input.wav')
x = np.float32(x)
y = np.zeros_like(x)

N  = 1024  # buffer block size = 23ms for a 44.1 Khz audio file
f = 1000  # cutoff
pos = 0  # position

while True:
    b, a = butter(2, 2.0 * f / sr, btype='low')
    y[pos:pos+N] = filtfilt(b, a, x[pos:pos+N])
    pos += N
    f -= 1   # cutoff decreases of 1 hz every 23 ms, but the issue described here also present with constant cutoff!
    print f
    if pos+N > len(x):
        break

y /= max(y)  # normalize

wavfile.write('out_fir.wav', sr, y)
我试过:

  • 使用巴特沃斯滤波器或FIR(将前面的行替换为
    b,a=firwin(1000,截止=f,fs=sr),1.0

  • 使用和(后者具有向前和向后应用过滤器的优势,这解决了相位问题)

但问题是:

在每个时间帧输出的边界处,存在连续性问题,这使得音频信号严重失真

如何解决这个不连续性问题?我考虑过窗口+重叠添加方法,但肯定有一种更简单的方法


正如@sobek在评论中提到的,当然需要指定初始条件以允许连续性。这是通过
lfilter
zi
参数完成的

通过以下方式更改主回路可解决此问题:

while True:
    b, a = butter(2, 2.0 * f / sr, btype='low')
    if pos == 0:
        zi = lfilter_zi(b, a)
    y[pos:pos+N], zi = lfilter(b, a, x[pos:pos+N], zi=zi)
    pos += N
    f -= 1 
    if pos+N > len(x):
        break

即使过滤器的截止值(因此,
a
b
)在每次迭代时都被修改,这似乎也能起作用。

因为您使用的是IIR过滤器,所以您需要将过滤器的状态从一个块保存到下一个块。不是参数,而是过滤器的状态,而是内存中的数据。如果你从一个块跳到下一个块,并使用一个完全未初始化的IIR过滤器,当然你会得到一个工件。处理的输出必须与未分块处理的相同,但缓冲的滞后除外。请查看
z_f
输出和
z_i
lfilt的输入参数。您需要将当前块的过滤器的
z_i
设置为上一块过滤器的
z_f
。这样,过滤器状态将从一个块持续到下一个块。来自dsp stackexchange的本主题可能也很有用。另外,了解过滤器内部构造的基本知识可能是一个好主意,这样做才有意义。@sobek谢谢!我贴出了答案。它似乎起作用了。你认为即使在每次迭代时截止值都发生变化的情况下(因此,
a
b
)也可以吗?我认为在这种情况下也可以。再加一条评论,如果只计算和更新过滤器系数(如果它们实际发生了变化),则可以节省性能。@sobek您可能会想到
filtfilt
的情况?