Python 在连续时间帧上应用IIR滤波器时的连续性问题
我想在每个1024个样本的连续块/时间帧上应用FIR或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
- 实时音频处理,如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
的情况?