Skip to main content
 首页 » 编程设计

python之20hz-20000hz巴特沃斯滤波爆炸式

2025年05月04日2498°冷暖

我想过滤掉 20 Hz - 20000 Hz 以外的所有内容。我正在使用 Butterworth 滤波器:

from scipy.io import wavfile 
from scipy import signal 
import numpy 
 
sr, x = wavfile.read('sweep.wav') 
nyq = 0.5 * sr 
b, a = signal.butter(5, [20.0 / nyq, 20000.0 / nyq], btype='band') 
 
x = signal.lfilter(b, a, x) 
x = numpy.float32(x) 
x /= numpy.max(numpy.abs(x)) 
wavfile.write('b.wav', sr, x) 

我注意到它适用于 44.1 khz 文件,但不适用于 96 khz WAV 文件 ( demo file here )(这不是音频 I/O 问题):输出是空白(无声)或爆炸(与一些其他输入 wav 文件)。

1) 是否存在导致 Butterworth 滤波器不适用于 b2 < 0.5 的带通 [b1, b2] 的原因?

2) 更一般地说,您将如何使用 Python/scipy 进行过滤以仅保持 20 - 20000Hz?(没有其他外部库)

请您参考如下方法:

scipy.signal.butter 正在生成一个不稳定的过滤器:

In [17]: z, p, k = signal.tf2zpk(b, a) 
 
In [18]: np.max(np.abs(p)) 
Out[18]: 1.0005162676670694 

对于稳定的过滤器,最大值必须小于 1。不幸的是,代码不会就此向您发出警告。

我怀疑问题出在 b1,而不是 b2。在归一化单位中,您试图创建一个非常小的 2.1e-4 下限。例如,如果下截止点是 200.0/nyq,则滤波器是稳定的:

In [13]: b, a = signal.butter(5, [200.0 / nyq, 20000.0 / nyq], btype='band') 
 
In [14]: z, p, k = signal.tf2zpk(b, a) 
 
In [15]: np.max(np.abs(p)) 
Out[15]: 0.99601892668982284 

您可以使用更强大的 sos(二阶部分)格式来代替过滤器使用 (b, a) 格式,该格式已添加到 scipy版本 0.16。要使用它,请更改这两行

b, a = signal.butter(5, [20.0 / nyq, 20000.0 / nyq], btype='band') 
x = signal.lfilter(b, a, x) 

到

sos = signal.butter(5, [20.0 / nyq, 20000.0 / nyq], btype='band', output='sos') 
x = signal.sosfilt(sos, x) 

SOS 过滤器不会遇到不稳定问题。