20Hz-20000Hz的Butterworth滤波器出问题了。

3

我希望将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千赫兹的文件,但无法处理96千赫兹的WAV文件演示文件在此)(这不是音频输入输出问题):输出要么是空白(没有声音),要么是爆炸声(对于其他一些输入wav文件)。
1)是否有什么原因导致Butterworth滤波器不能用于带通[b1,b2],其中b2 < 0.5?
2)总的来说,你如何使用Python/scipy进行过滤,只保留20-20000Hz的声音?(不使用其他外部库)

错误的堆栈。请尝试dsp.stackexchange.com。 - wwii
Scipy是一个外部库。 - wwii
1个回答

8

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)

to

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

那个SOS过滤器不会受到不稳定性问题的困扰。

谢谢!我们应该在这里添加一个警告提示,提醒用户可能会出现不稳定的情况,因为文档中没有提到。还有一个问题:你怎么知道我们应该使用sos?对我来说听起来像是魔法 :) sos在这里没有被记录:https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.butter.html。它是否类似于`zpk`? - Basj
顺便说一下,我完全随机选择了Butterworth滤波器,你会用哪种方法来过滤掉20-20000Hz之外的所有内容?我在DSP.se上发布了一个问题:http://dsp.stackexchange.com/questions/36564/filtering-everything-outside-20-20000-hz - Basj
"sos在此未有文件记录:[...]"您提供了scipy 0.14的文档链接。第一个SOS代码是在版本0.16中添加到scipy中的。 - Warren Weckesser
DSP StackExchange是提出使用哪种滤波器的正确场所,看起来您已经收到了一个好答案。 - Warren Weckesser
谢谢,你说得对,我现在在Scipy 0.16文档中找到了它。顺便说一下,你的巴特沃斯sos滤波器解决方案很好! - Basj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接