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

时间:2018-09-23 17:26:50

标签: python numpy audio scipy signal-processing

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

可能的应用程序:

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

  • 按照建议in this answer,通过将输入信号分成多个块来制作一个随时间变化的截止滤波器。

我在这里尝试过

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)

我尝试过:

  • 同时使用Butterworth滤波器或FIR(用b, a = firwin(1000, cutoff=f, fs=sr), 1.0替换前一行)

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

但这是问题所在:

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

如何解决这种不连续性问题?我曾考虑过windowing + OverlapAdd方法,但是肯定有一种更简单的方法。

enter image description here

1 个答案:

答案 0 :(得分:2)

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

通过更改主循环可以解决此问题:

lfilter

即使在每次迭代中都修改了过滤器的截止时间(因此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),这似乎仍然有效。