Sanjith T
Sanjith T

Reputation: 11

Filter coefficients not working when directly implemented on to a audio file?

When I use the butter function from scipy for a bandpass filter of order 4 onto a .wav audio file, it is working but when I use the same filter coefficients directly on to the same audio it is not working.

I'm trying to implement a bandpass filter on a .wav audio file using Python. Initially, I used the butter function from scipy to generate filter coefficients and applied the filter using filtfilt, which worked fine. However, when I tried to directly use the same filter coefficients with lfilter, I didn't get the expected results. Here's what I've tried:

First, here's the code that worked using filtfilt:

from scipy.signal import butter, filtfilt
from scipy.io import wavfile

def butter_bandpass(lowcut, highcut, fs, order=4):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a

def butter_bandpass_filter(data, lowcut, highcut, fs, order=4):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = filtfilt(b, a, data)
    return y

filename = "Heart Data 1 (1).wav"
fs, data = wavfile.read(filename)

lowcut = 30
highcut = 450
order = 4

b, a = butter_bandpass(lowcut, highcut, fs, order=order)
print("Filter Coefficients (b):", b)
print("Filter Coefficients (a):", a)

filtered_data = butter_bandpass_filter(data, lowcut, highcut, fs, order=order)

This code produced the desired filtered audio with the coefficients

b = [3.76138361e-05, 0.00000000e+00, -1.50455344e-04, 0.00000000e+00,
     2.25683017e-04, 0.00000000e+00, -1.50455344e-04, 0.00000000e+00,
     3.76138361e-05]
a = [1.0, -7.56134654, 25.03021633, -47.37940103, 56.09188775,
     -42.53071304, 20.16985559, -5.46999014, 0.64949108]

However, when I tried to use the same filter coefficients directly with lfilter, I didn't get the expected results:

from scipy.signal import lfilter
from scipy.io import wavfile

filename = "Heart Data 1 (1).wav"
fs, data = wavfile.read(filename)

b = [3.76138361e-05, 0.00000000e+00, -1.50455344e-04, 0.00000000e+00,
     2.25683017e-04, 0.00000000e+00, -1.50455344e-04, 0.00000000e+00,
     3.76138361e-05]
a = [1.0, -7.56134654, 25.03021633, -47.37940103, 56.09188775,
     -42.53071304, 20.16985559, -5.46999014, 0.64949108]

filtered_data = lfilter(b, a, data)

This code didn't produce the desired filtered audio.

I expected both methods to produce the same filtered audio since I used the same filter coefficients. Can someone help me understand what might be going wrong with the second method using lfilter? Thank you!

Upvotes: 1

Views: 67

Answers (1)

dankal444
dankal444

Reputation: 4138

Lfilter is different than filtfilt.

lfilter method applies filtering once, using standard method

a[0]*y[n] = b[0]*x[n] + b[1]*x[n-1] + ... + b[nb]*x[n-nb]
                        - a[1]*y[n-1] - ... - a[na]*y[n-na]

filtfilt method applies filtering twice, each time using the standard method as above, but second time it does it with reversed signal. So:

  • it removes delay (to be precise, adds delay twice but second one cancels the first one)
  • since signal is filtered twice it can be interpreted as doubling filter order

Upvotes: 2

Related Questions