How to plot an eq curve

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hi,
I'm trying to make a graphical user interface for a 4-band equalizer, and I'm wondering if anyone has any hints about how I could plot the actual eq curve according to the current settings.. e.g. band frequency, band width, gain and so on.

To clarify, the screenshot below shows the type of curve I'm trying to implement to visualize the eq-settings (although I'm only interested in one curve and not two as shown here):

Image

What sort of mathematical function would be appropriate to use for this? Any pointers would be greatly appreciated.


Thanks!

Post

Why not take samples of the actual magnitude response and connect the points via some kind of spline/interpolation? There are surely some interpolation classes on the net...
Cheers
Sören
und doch, doch, und doooooch!

Post

virtualinsanity wrote:Why not take samples of the actual magnitude response and connect the points via some kind of spline/interpolation? There are surely some interpolation classes on the net...
Cheers
Sören
Because that would'nt show the eq curve ? That's spectral analysis and is input dependent.

If i were to do this i would have an array of values that reperesents each pixel that initialized to 0.0f. For each pixel i would add a weight from each eq "point" where the weight depends on the distance to the point ( the bandwitdh of the filter) ,the gain of the filter and the filter curve (the Q value).

The first two are really simple to implement but i'm not sure how to do the Q scaling. Some sort of exponetial/logarithmic (i swear one day i will learn the difference) :) scaling should do the trick.

Post

on musicdsp george yohng has posted some code that if you feed it your filter coefficients, and give it a frequency, it will give you the magbitude response at that point... do it for each filter at selected pixels, then combine for overall response ;)

HTH
DSP
Image

Post

duncanparsons wrote:on musicdsp george yohng has posted some code that if you feed it your filter coefficients, and give it a frequency, it will give you the magbitude response at that point... do it for each filter at selected pixels, then combine for overall response ;)

HTH
DSP
That's quite what I meant saying "take samples of the actual magnitude response"... Only I forgot this wasn't trivial because I use code for it I haven't written myself. Sorry...
und doch, doch, und doooooch!

Post

Really easy - use FFT. Send a single 1.0f sample followed by however many 0.0f samples you need through your EQ, then perform a FFT on that. Convert to magnitude respnse form and presto ;)
Cakewalk by Bandlab / FL Studio
Squire Stratocaster / Chapman ML3 Modern V2 / Fender Precision Bass

Formerly known as arke, VladimirDimitrievich, bslf, and ctmg. Yep, those bans were deserved.

Post

jupiter8 wrote:
virtualinsanity wrote:Why not take samples of the actual magnitude response and connect the points via some kind of spline/interpolation? There are surely some interpolation classes on the net...
Cheers
Sören
Because that would'nt show the eq curve ? That's spectral analysis and is input dependent.

If i were to do this i would have an array of values that reperesents each pixel that initialized to 0.0f. For each pixel i would add a weight from each eq "point" where the weight depends on the distance to the point ( the bandwitdh of the filter) ,the gain of the filter and the filter curve (the Q value).

The first two are really simple to implement but i'm not sure how to do the Q scaling. Some sort of exponetial/logarithmic (i swear one day i will learn the difference) :) scaling should do the trick.
That sounds like a good idea jupiter8. I think spectral analysis will be overkill for this application, as the curve is only meant to be a visual aid to make the different eq-parameters easier to understand for the user. So, the curve should not need to be dependent on specific characteristics of the filters.
Anyone else have any ideas along these lines?

Post

why bother with an FFT when it's possible to evaluate the magnitude and phase response directly at any point you want (log/lin/semi/3rd-octave...) via its Z-transform?

if you have:

Code: Select all

       b0 + b1*z^-1 + b2*z^-2
H(z) = ----------------------
        1 + a1*z^-1 + a2*z^-2
then

Code: Select all

Magnitude(f) = abs( H(z) )
Phase(f) = arg(H(z))
z = exp(i*2*pi*f)
f is the normalized frequency.

you can do it using std::complex

Code: Select all

std::complex<double> z = std::polar(1.f, 2*pi*f);
std::complex<double> z2 = z*z;
std::complex<double> h = (b0*z2 + b1*z + b2) / (z2 + a1*z + a2);
float mag   = abs(h);
float phase = arg(h);
notice that I have multiplied the numerator and denominator by z^2 to avoid some complex divisions.

you can do this with any Z transfer function.
Last edited by mdsp on Mon Jun 29, 2009 9:58 am, edited 2 times in total.

Post

plotting the true frequency response would go like this:

first, identify each x-coordinate of your drawing area with a frequency - you will probably want some log-scaling of the frequency axis for this. now calculate the magnitude of your EQ at these frequencies (and most probably, you will want convert that to dB). that magnitude value must now be converted into an y-coordinate of your drawing area. you end up with a set of x- and y-coordinates in your drawing area measured in units of pixels. connect all pixels so obtained with straight lines - because the x-distance between each pair of node coordinates is just one pixel, it is pointless to use more sophisticated interpolation here.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

Thanks for all your suggestions, I will try this out!

Post

mdsp wrote: you can do it using std::complex

Code: Select all

std::complex<double> z = std::polar(2*pi*f);
std::complex<double> z2 = z*z;
std::complex<double> h = (b0*z2 + b1*z + b2) / (z2 + a1*z + a2*z);
float mag   = abs(h);
float phase = arg(h);
Hi, I've tried this code. I can't get it to work however. I calculate f (the normalized frequency) as f/samplerate, yielding a value in the range of 0.0 to 0.5. I run this calculation for a selection of points along the frequency axis, and then use the resulting mag variable to determine the position of the curve at this point. The resulting curve has a very erratic behaviour though. It seems to show peaks at random locations, and when slowly sweeping the frequency, the eq curve sort of ripples along. It seems that the values are "wrapping around" the frequency axis very quickly so to speak. I guess there is some kind of intermediate calculation that I'm missing here? Any suggestions?
I could probably supply some screenshots if that would help clarify the problem.

Post

There is a small typo in mdsp's version, it should actually be

Code: Select all

h = (b0*z2 + b1*z + b0)/(z2 + a1*z +a2)
(so only a2 instead of a2*z).

Post

Thanks mdsp and docdued. I was also looking for that :)

Post

You could also do it directly from the s domain transfer function for fun http://malaysia.answers.yahoo.com/quest ... 504AA85hg0
Matt

Pi is exactly three

Post

hill_matthew wrote:You could also do it directly from the s domain transfer function for fun
sure he can, but why should he? i see two drawbacks:

1. it only works for filters which are derived from analog (s-domain) prototypes
2. it plots the 'wrong' frequency response (by ignoring the frequency-warping from the bilinear transform (which i assume to be used))

O.K., you said for fun.....but in a real product (albeit possibly freeware), one thing i just can't stand are dishonest plots
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post Reply

Return to “DSP and Plugin Development”