# Bandpass butterworth filter in python is not working

I've implemented this bandpass filter in matlab for the audio signals and it's working as expected. Now, I tried to implement the same thing in Python but it doesn't produced expected results, it just sort of discard the whole signal.

Here is the Matlab code:

[f,fs] = audioread('abc.wav');
n=6; %order
beginFreq = (300/(fs/2));
endFreq = (2300/(fs/2));
[b,a] = butter(n,[beginFreq,endFreq],'bandpass');
%filter the signal
filtered = filter(b,a,signal);


Here is the Python code (using scipy.signal)

[originalSignal, sampleRate] = sf.read('abc.wav')
lower = (300/(sampleRate/2))
higher = (2300/(sampleRate/2))
n=6 #order
[b, a] = signal.butter(n, [lower, higher], 'bandpass')
filtered = signal.lfilter(b, a, originalSignal)
plt.plot(originalSignal, 'b', filtered,'r')


There is one more weird thing with the output! I tried to change the values of the lower and higher frequencies. As the frequency range increases; only the amplitude of output signal increases from 'almost zero' to higher value. For example, when I give the lower and higher frequency values as '100.0' and '13000' respectively, the output signal is "same" as the input signal but with almost half the amplitude. So, apparently the filter is not affecting the frequencies at all but rather affecting the amplitude..... I've no idea what's going on... :(

• @MarcusMüller I'm using Python 3. I've tried both format values (300.0 & 300) – Ali Nisar Haider Jul 19 '18 at 7:52
• Have you compared the filter coefficients? – Irreducible Jul 19 '18 at 8:13
• @Irreducible How..? If You can please elaborate. – Ali Nisar Haider Jul 19 '18 at 8:20
• [originalSignal, sampleRate] = sf.read('abc.wav') ... what [ ] means in python ? .. do you need to have them there? – Juha P Jul 19 '18 at 8:21
• @JuhaP this is the command just to read the audio file in python. studiofile.read('abc.wav) – Ali Nisar Haider Jul 19 '18 at 9:22

Did you finally solve this issue?

For what I can see in the code and the signals, two different reasons comes to my mind:

1) Try adding the parameter 'analog=False' to signal.butter. You should specify that the signal is not continuous but discrete:

b, a = signal.butter(n, [lower, higher], 'bandpass', analog=False)

b, a = sg.butter(5, [300.0/10000.0, 2300.0/10000.0],'bandpass', analog=True)

b,a
Out[17]:
(array([0.00032, 0.     , 0.     , 0.     , 0.     , 0.     ]),
array([1.00000000e+00, 6.47213595e-01, 2.43942719e-01, 5.97516391e-02,
9.98927305e-03, 1.08294494e-03, 6.89259840e-05, 2.84477554e-06,
8.01373787e-08, 1.46704689e-09, 1.56403135e-11]))

b, a = sg.butter(5, [300.0/10000.0, 2300.0/10000.0],'bandpass', analog=False)

b,a
Out[19]:
(array([ 0.00128258,  0.        , -0.00641291,  0.        ,  0.01282581,
0.        , -0.01282581,  0.        ,  0.00641291,  0.        ,
-0.00128258]),
array([  1.        ,  -7.69615728,  26.91430318, -56.40566369,
78.54031013, -75.97473091,  51.72325998, -24.47255607,
7.70127426,  -1.45546962,   0.12543062]))


2) The filter order is too big for python to be computed properly (Matlab may use different stability methods to achieve the final result or a different process to filter the signal)

The matlab function takes input values for the filter order as $$n/2$$ for bandpass/bandstop-design, meaning your matlab resulting filter should have $$n=12$$. For your python code, this has to be accounted for as the python version of the design routine does not show this behaviour.

The documentation of both functions:

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html

https://www.mathworks.com/help/signal/ref/butter.html