В соответствии с уравнениями (5) и (6) из ANSI S1.11: Спецификация для наборов полосовых фильтров октавы, полуоктавы и третьей октавы , для 1/3 октавы - нижняя и верхняяЧастоты каждой полосы определяются следующим образом:
factor = np.power(G, 1.0/6.0)
lowerCutoffFrequency_Hz=centerFrequency_Hz/factor;
upperCutoffFrequency_Hz=centerFrequency_Hz*factor;
Где G
равно либо 2 (при разработке фильтров в соответствии с указанными правилами base-2), либо np.power(10, 0.3)
(при разработке фильтров в соответствии с указаннымиправила базы-10).В вашем случае предоставленные вами центральные частоты близки к значениям, полученным с использованием правил base-2, поэтому вам также следует G = 2
быть последовательным.
Обратите внимание, что для вашего заданного массива центральной частоты есть несколько значенийиз верхних частот будет больше, чем частота Найквиста (половина вашей частоты дискретизации).Соответственно, при попытке создать фильтр с scipy.signal.butter
они будут давать недопустимые верхние значения нормализованной частоты.Чтобы избежать этого, вы должны ограничить массив центральной частоты значениями, меньшими, чем ~ 19644 Гц:
centerFrequency_Hz = np.array([39, 50, 63, 79, 99, 125, 157, 198, 250, 315,
397, 500, 630, 794, 1000, 1260, 1588, 2000, 2520, 3176, 4000, 5040, 6352, 8000, 10080,
12704, 16000])
Кроме того, scipy.signal.butter
может обрабатывать один набор низких и верхних частот одновременно,поэтому вы должны зациклить массивы нижней и верхней частот для разработки каждого полосового фильтра:
for lower,upper in zip(lowerCutoffFrequency_Hz, upperCutoffFrequency_Hz):
# Determine numerator (b) and denominator (a) coefficients of the digital
# Infinite Impulse Response (IIR) filter.
b, a = signal.butter( N=4, Wn=np.array([ lower,
upper])/nyquistRate, btype='bandpass', analog=False,
output='ba');
# Compute frequency response of the filter.
w, h = signal.freqz(b, a)
plt.plot(w, 20 * np.log10(abs(h)), 'b')
# Filter signal
filteredSpeech = signal.filtfilt(b, a, speech)
Это должно дать вам график, подобный следующему для амплитудных откликов:
В этот момент вы можете заметить некоторые признаки нестабильности в нижней полосе.Чтобы избежать этой проблемы, вы можете переключиться на представление sos
:
for lower,upper in zip(lowerCutoffFrequency_Hz, upperCutoffFrequency_Hz):
# Design filter
sos = signal.butter( N=4, Wn=np.array([ lower,
upper])/nyquistRate, btype='bandpass', analog=False,
output='sos');
# Compute frequency response of the filter.
w, h = signal.sosfreqz(sos)
plt.plot(w, 20 * np.log10(abs(h)), 'b')
# Filter signal
filteredSpeech = signal.sosfiltfilt(sos, speech)