# System identification/ Filter estimation to mimic frequency equalizer of audio with Scipy

At the current problem I'm working on, I have two signals: One "original" signal that contains audio (voice). The second signal is the same audio file but edited with a frequency equalizer, for example to make all frequencies between $649-677\textrm{ Hz}$ louder.

What I'm trying to achieve now is to "teach" a SCIPY filter to mimic this behavior. Therefore I created a function with two butterworth-filters and try to curve_fit the $x$-data to the $y$-data. The intuition is, that like this the system learns the optimal frequency intervals to mimic the equalizer. Obviously it doesn't work as supposed (no curve fit achieved most of the time. If I achieve a curve fit and apply the filter to the original data, it didn't change at all). Any suggestions?

import numpy as np
from scipy.optimize import curve_fit
from scipy import signal

xdata = voice_1
ydata = voice_2

# Function to optimize, supposed that two bandpass filters are enough
def func(x, p1,p2,p3,p4):
b, a = signal.butter(2,[p1,p2],btype="band")
x = signal.lfilter(b,a,x)
b, a = signal.butter(2,[p3,p4],btype="band")
x = signal.lfilter(b,a,x)
return x

# Optimize function to achieve a curve-fit and therefore get the right frequency response in p1,p2,p3,p4
popt, pcov = curve_fit(func, xdata, ydata,p0=(0.5,0.5,0.5,0.5))


What I also tried was creating a xsignal containing of white-noise, creating a ysignal where I changed some frequency levels and calculating a transfer function H as FFT(ysignal)/FFT(xsignal). As soon as I apply this function to other data than white noise the results seem to be wrong as well.

• "seem to be wrong": how do you figure? could you plot e.g. the in-, reference and output PSDs? Jun 13 '16 at 10:53
• Jomona, you could try a time domain equailizer using your two signals and the Wiener-Hopf equations - see dsp.stackexchange.com/questions/31318/… and mathworks.com/matlabcentral/fileexchange/… . I think this would work quite well for you and be a "least squared error" solution. Jun 13 '16 at 12:33
• "As soon as I apply this function to other data than white noise the results seem to be wrong as well." Are you looking at magnitude and phase of the output separately? Jun 13 '16 at 15:41
• Thanks for all your comments. Regarding the last one: I make an IFFT and get the signal back into the time-domain. There I only look at the Amplitude over time. @ Dan Boschen: Thanks for the link. This got me to think about the filtering solely in the time-domain. Maybe I can come up with a solution here. Jun 13 '16 at 16:38

Thanks for all your comments. I finally found the answer this article and implemented it in python:https://www.dsprelated.com/freebooks/filters/Time_Domain_Filter_Estimation.html It works pretty well, if you first find the transfer function h(t) with raw and equalized white noise and then apply the function as a filter to any audio data:

import numpy as np
import scipy

def learn_equalizer(signal_x, signal_y, detail_level):
# Create Toeplitz Matrix
X = scipy.linalg.toeplitz(first_col, first_row)

# Implement the formula for finding the optimal solution numerically
X = X[0:len(X)-detail_level,]
h = np.dot(X.T,X)
h = scipy.linalg.inv(h)
h = np.dot(h,X.T)
equalizer = np.dot(h,signal_y)

return equalizer


Finally looking at the curves let's consider two plots: One with the raw and equalized signal, to show their differences. The other plot shows the equalized signal and the "mimicked" equalizer. Here you see how good the learned filter is, when applied to real sounds after being trained on white noise.

Signal comparison: