在连续的时间帧上应用IIR滤波器时的连续性问题 [英] Continuity issue when applying an IIR filter on successive time-frames
问题描述
我想对每个连续1024个样本的连续块/时间帧应用FIR或IIR滤波器(例如:低通滤波器).
I would like to apply a FIR or IIR filter (example: lowpass filter) on successive blocks/time-frames of 1024 samples each.
可能的应用程序:
-
实时音频处理,例如EQing.在准确的时间,缓冲区中只有接下来的1024个样本.下一个要处理的样本尚不可用(实时).
realtime audio processing, such as EQing. At a precise time, we only have the next 1024 samples in a buffer. The next samples to process are not available yet (realtime).
按照输入答案中的建议在此答案中制作一个时变截止滤波器,方法是将输入信号分成多个块. >.
make a cutoff-time-varying filter by splitting the input signal in blocks, as suggested 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
替换之前的行)
两者都带有 lfilter
和 filtfilt
(后者具有向前和向后应用过滤器的优势,这解决了相位问题),
both with lfilter
and filtfilt
(the latter has the advantage to apply the filter forward and backwards, and this solves phase issues),
但这是问题所在:
**在每个时间帧输出的边界处,存在连续性问题,这会使音频信号严重失真.
**At the boundaries of each time-frames' output, there is a continuity issue, that makes the audio signal heavily distorded.
如何解决这种不连续性问题?我曾考虑过windowing + OverlapAdd方法,但是肯定有一种更简单的方法.
How to solve this discontinuity problem? I thought about windowing+OverlapAdd method, but there surely must be an easier way.
推荐答案
正如@sobek在评论中提到的,当然需要指定初始条件以允许连续性.这是通过lfilter
的zi
参数完成的.
As mentioned by @sobek in a comment, it's of course needed to specify the initial conditions to allow continuity. This is done with the zi
parameter of lfilter
.
通过以下方法更改主循环即可解决该问题:
The problem is solved by changing the main loop by:
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
),这似乎仍然有效.
This seems to work even if the filter's cutoff (and thus the a
and b
) is modified at each iteration.
这篇关于在连续的时间帧上应用IIR滤波器时的连续性问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!