在连续时间帧上应用 IIR 滤波器时的连续性问题
Continuity issue when applying an IIR filter on successive time-frames
我想应用 FIR 或 IIR 滤波器(示例:低通滤波器)对每个 1024 个样本的连续 blocks/time-frames。
可能的应用:
实时 音频处理,例如 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
)
-
但问题是:
在每个时间帧输出的边界处,存在连续性问题,导致音频信号严重失真。
这个不连续的问题怎么解决?我想到了windowing+OverlapAdd的方法,但肯定有更简单的方法。
正如@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
),这似乎也有效。
我想应用 FIR 或 IIR 滤波器(示例:低通滤波器)对每个 1024 个样本的连续 blocks/time-frames。
可能的应用:
实时 音频处理,例如 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
)
但问题是:
在每个时间帧输出的边界处,存在连续性问题,导致音频信号严重失真。
这个不连续的问题怎么解决?我想到了windowing+OverlapAdd的方法,但肯定有更简单的方法。
正如@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
),这似乎也有效。