【发布时间】:2019-02-27 07:54:39
【问题描述】:
我想在每个 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)
我试过了:
-
都带有巴特沃斯滤波器或 FIR(将前面的行替换为
b, a = firwin(1000, cutoff=f, fs=sr), 1.0)
但问题出在这里:
在每个时间帧输出的边界处,存在连续性问题,导致音频信号严重失真。
如何解决这种不连续性问题?我想过windowing+OverlapAdd方法,但肯定有更简单的方法。
【问题讨论】:
-
由于您使用的是 IIR 过滤器,因此您需要将过滤器的状态从一个块持续到下一个块。
-
不是参数,过滤器的状态,内存中的数据。如果您从一个块跳到下一个块并使用完全未初始化的 IIR 滤波器,那么您当然会得到一个伪像。处理的输出必须与未按块处理时的输出相同,但缓冲的延迟除外。
-
查看
lfilt的z_f输出和z_i输入参数。您需要将当前块的过滤器的z_i设置为前一个块的过滤器的z_f。这样,您的过滤器状态就会从一个块持续到下一个块。来自 dsp stackexchange 的这个主题也可能有用。 dsp.stackexchange.com/questions/28725/… 另外,您最好了解一下如何在内部构建过滤器的基础知识,所以这一切都很有意义。 -
@sobek 谢谢!我发布了一个答案。它似乎工作。你认为即使在每次迭代中截止值都发生变化的情况下也可以(因此
a,b也是如此)? -
我认为在这种情况下还可以。
标签: python numpy audio scipy signal-processing