20hz-20000hz巴特沃斯过滤爆炸

Bas*_*asj 1 python filtering signal-processing numpy scipy

我想过滤掉20 Hz - 20000 Hz以外的所有信号.我正在使用巴特沃斯滤波器:

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)
Run Code Online (Sandbox Code Playgroud)

我注意到它适用于44.1 khz文件,但没有96 khz WAV文件(这里是演示文件)(它不是音频I/O问题):输出是空白(静音)或爆炸(有些其他输入wav文件).

1)是否存在使Butterworth滤波器不能用带通[b1,b2] b2 <0.5的东西?

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

War*_*ser 5

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

In [17]: z, p, k = signal.tf2zpk(b, a)

In [18]: np.max(np.abs(p))
Out[18]: 1.0005162676670694
Run Code Online (Sandbox Code Playgroud)

对于稳定的过滤器,该最大值必须小于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
Run Code Online (Sandbox Code Playgroud)

(b, a)您可以使用更健壮的sos(二阶段)格式,而不是使用过滤器的格式,该格式已添加到scipy版本0.16.要使用它,请更改这两行

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

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

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