2016-12-29 8 views
1

Я хочу отфильтровывать все за пределами 20 Гц - 20000 Гц. Я использую фильтр Баттерворта:20hz-20000hz Взрывная фильтрация 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 файл (demo file here) (это не проблема аудио ввода/вывода): выход либо пустой (тишина), либо взрыва (с некоторыми другими входными wav-файлами).

1) Есть ли что-то, что делает фильтры Баттерворта не работающими с полосой пропускания [b1, b2] где b2 < 0,5?

2) В целом, как бы вы сделали фильтрацию, чтобы сохранить только 20 - 20000 Гц с помощью Python/scipy? (никакая другая внешняя библиотека)

+0

Неверный стек. Попробуйте dsp.stackexchange.com. – wwii

+0

Scipy - это внешняя библиотека. – wwii

ответ

4

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 

Вместо того чтобы использовать формат (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) 

в

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

Это SOS фильтр не страдает от проблемы неустойчивости.

+0

Спасибо! Мы должны добавить [предупреждение] здесь (https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.butter.html) о нестабильности, потому что это не упоминается. Что-то еще: откуда вы знаете, что мы должны использовать 'sos'? Это звучит как волшебный для меня :) 'sos' здесь не зарегистрирован: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.butter.html. Это похоже на 'zpk'? – Basj

+0

Btw, я выбрал Butterworth совершенно наугад, какое решение вы бы использовали для фильтрации всего за 20 - 20000 Гц? Я начал вопрос DSP.se здесь: http://dsp.stackexchange.com/questions/36564/filtering-everything-outside-20-20000-hz – Basj

+0

* «sos не зарегистрирован здесь: [...]" * Вы указали ссылку на документацию для scipy 0.14. Первый код SOS был добавлен в scipy в версии 0.16. –