How to plot an eq curve

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

For some reason

Code: Select all

std::complex<double> z = std::polar(2*pi*f);  
didn't work for me and I had to use

Code: Select all

std::complex<double> z(cos(2*pi*f), sin(2*pi*f));
to get the polar for z.

Also the final post of the code was

Code: Select all

std::complex<double> h = (b0*z2 + b1*z + b0) / (z2 + a1*z + a2);
but I found the typo correction introduced another, so I suggest

Code: Select all

std::complex<double> h = (b0*z2 + b1*z + b2) / (z2 + a1*z + a2);
to be correct. Finally to get the frequency shouldn't

Code: Select all

float mag = real(h); 
be used rather than

Code: Select all

float mag = abs(h); 
as using abs can't give a negative value.
Matt

Pi is exactly three

Post

hill_matthew wrote:Finally to get the frequency shouldn't float mag = real(h); be used rather than float mag = abs(h); as using abs can't give a negative value.
Usually if you want to plot an EQ curve you don't want the real part of h but it's magnitude which by definition is >= 0.

If you're confused by the fact that in decibels, the magnitude can be negative then you can just use

Code: Select all

magdB = 20*log10(abs(h));

Post

It's easier to think of the complex response in of the form R*e^(i*A) (that is, in polar form) where quite directly R is the (real, positive) amplitude, and A is the phase shift (real, and can be normalized to [0,2*pi] unless need to concern yourself with the time-domain properties).

So amplitude is the complex magnitude, and phase is the argument.

Post

mdsp wrote:
hill_matthew wrote:Finally to get the frequency shouldn't float mag = real(h); be used rather than float mag = abs(h); as using abs can't give a negative value.
Usually if you want to plot an EQ curve you don't want the real part of h but it's magnitude which by definition is >= 0.

If you're confused by the fact that in decibels, the magnitude can be negative then you can just use

Code: Select all

magdB = 20*log10(abs(h));
Of course, how silly of me :)
Matt

Pi is exactly three

Post

Hi everybody ,
im a software engineering student and im suppose to do the same thing. i should make a Parametric EQ , which it has 3 trackbars for Gain (-15 to + 15 ) Frequency (20Hz to 20 KHz) and Q-Factor (0.5 to 9.0). and i draw the curve by changing the trackbar values .

as i gone trough the answers here and seen the Websites i clculated a0,a1,a2,b0,b1 and b2 based on the codes down here (VB.NET). and since my praph is 600 pixel(x axis - frequency) to 300 pixel( y axis - Gain), and i sould draw the curve based on magnitude (frequency should be in log form).

in this code i have calculated the values for a0,a1,a2,b0,b1 and b2 then by using a 'for loop' i calculate the magnitude for each loop(each i - frequency (x axis)) but still i cannt have the curve . if you help me to check whether i calculate a0,a1,a2,b0,b1 and b2 and finally magnitudevalue values by correct fromula i will be really thanksful .

Dim z As Single
Dim z2 As Single

'Calculate the magnitude values
For i As Integer = 1 To Graph(myKey).ptsArray.Length
MagnitudeValue = 0.0

z = Cos(2 * PI * (i - TrackFreq.Value))
z2 = z * z
MagnitudeValue = (b0 * z2 + (b1 * z) + b0) / (z2 + (a1 * z) + a2)

next i

'i value represets x axis and MagnitudeValue represents magnitude vlue in graph
Last edited by Bluebirdglory on Tue Jun 30, 2009 4:39 am, edited 1 time in total.

Post

Bluebirdglory wrote:if you help me to check whether i calculate a0,a1,a2,b0,b1 and b2 and finally magnitudevalue values by correct fromula i will be really thanksful .


Dim z As Single
Dim z2 As Single


'Calculate the magnitude values
For i As Integer = 1 To Graph(myKey).ptsArray.Length
MagnitudeValue = 0.0

z = Cos(2 * PI * (i - TrackFreq.Value))
z2 = Zz * Zz
MagnitudeValue = (b0 * z2 + (b1 * z) + b0) / (z2 + (a1 * z) + a2)
looks like your z, z2 variables are real numbers (i'm not familiar with that programming language)? they should be complex. and then afterwards you would extract the magnitude. ...or evaluate the magnitude response directly. i posted a c++ code snippet and a link to a document with the appropriate formula near the bottom of page 1 of this thread:

http://www.kvraudio.com/forum/viewtopic.php?t=248806
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

looks like your z, z2 variables are real numbers (i'm not familiar with that programming language)? they should be complex. and then afterwards you would extract the magnitude. ...or evaluate the magnitude response directly. i posted a c++ code snippet and a link to a document with the appropriate formula near the bottom of page 1 of this thread:

http://www.kvraudio.com/forum/viewtopic.php?t=248806
Yes you are right i tranfered them to Complex form now. but it seem still its a long way to see EQ curve. :help: . let me explain a bit more clear what i have done by now, but its quite long time i cannt see the curve. sth around is going wrong, and made me quite disappointed.

actually after i calculate b0,...a2 based on these formulas :

Code: Select all

CenterFreqValueExp = (10 * (10 ^ (TrackbarFreq.Value / 200)))
'my frequency trackbar is from 0 to 600 and i used this formula to calculate correspondant frequency value for each pixel since x axis is in log form

Code: Select all

        Fs = 1.0 / 48000.0   'sample frame rate
        Gain = TrackbarGain.Value 'from [-15 to +15]  
        F0 = CenterFreqValueExp
        Q = (TrackQfactor.Value) ' from [0.5 to 9.0]
'these formulas from wesite: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

Code: Select all

        A = 10 ^ (Gain / 40) 'here im not sure why it has devided by 40
        Omega = 2 * PI * F0 * Fs
        alpha = Sin(Omega) / (2 * Q)

        b0 = 1 + (alpha * A)
        b1 = -2 * Cos(omega)
        b2 = 1 - (alpha * A)
        a0 = 1 + (alpha / A)
        a1 = -2 * Cos(omega)
        a2 = 1 - (alpha / A) 
After values calculated im really lost bcuz there are number of different fromulas which i dono which one should i use however i have tried them but still i couldn see the curve : the are the formulas which i use them in a FOR LOOP(represents going forward on X axis i=0 to 600 - frequency) to calculate the Y axis value to draw the curve.

Code: Select all

        For i As Integer = 1 To 600 
            iExp = (10 * (10 ^ (i / 200))) ' in here i covert i to its exponential value since X axis is in Log form

            Y_axisValue = 0.0 'variable to calculate y axis value
         ...
'and now here the number of formulas which i dono which one i should use to calculate Y_axis value : ( i dono whether i should use tranfer function or Magnitude response formula)


1: Transfer Function:

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

actually i have used this formula inside FOR LOOP in this way :
''''''''''''''''''''''''''''''''''''''''''''''''''''''

Code: Select all

            z = Complex.Polar(iExp * 2 * PI * F0 * F0)  ' I put 'i' value (i Exp)in here then
        
            Y_axisValue = Complex.Abs(b0 + (b1 * (Pow(z, -1))) + (b2 * (Pow(z, -2))) / (1 + (a1 * (Pow(z, -1))) + (a2 * (Pow(z, -2)))))

'and like this i calculated Y value for each Y point, That i think you can guess what was the result . :shock:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''

2: http://www.kvraudio.com/forum/viewtopic ... c&start=15
second by refering to this post i used the formulas in Page 2 to calculate z and Y-Axis value:


std::complex<double> z(cos(2*pi*f), sin(2*pi*f));
std::complex<double> h = (b0*z2 + b1*z + b2) / (z2 + a1*z + a2);

:

Code: Select all

            z = Complex(Cos(2 * PI * F0 * Fs), Sin(2 * PI * F0 * Fs))
            z2 = z * z
            Y-Axis value = Complex.Abs(((b0 * z2) + (b1 * z) + b0) / (z2 + (a1 * z) + a2))
' actaully i didn know were should i put 'i' (iExp) value ,means x value to get the Y value. and i put it inside Sin and Cos means Cos (2 * iExp ...)


and finally I refers to the link you have posted ehich is using C++ in the prvs post and by using that formula also the result was the same.

and also by changing any of the Trackbars (F, Q or G) the the whole shape changes, I need the cure move on X axis only if i change F , or get wide only if i change Q or its height increase and decrease only by changing the G (Gain value)


.. if you can help me to know what is going wrong and which one i should use to be able to draw this curve and also where should i change the iExp (counter in For Loop) i will be so thanksfull.

Post

in your case iExp is the frequency in Hz (going from 10hz to 10kHz from your formula)

there's a mistake here:

Code: Select all

z = Complex(Cos(2 * PI * F0 * Fs), Sin(2 * PI * F0 * Fs))
it should be:

Code: Select all

f = iExp / Fs
z = Complex(Cos(2 * PI * f), Sin(2 * PI * f))

Post

mdsp wrote:in your case iExp is the frequency in Hz (going from 10hz to 10kHz from your formula)

there's a mistake here:
z = Complex(Cos(2 * PI * F0 * Fs), Sin(2 * PI * F0 * Fs))

it should be:
f = iExp / Fs
z = Complex(Cos(2 * PI * f), Sin(2 * PI * f))
Thanks for the reply . I have changed F0 to iExp and since my Fs = 1/ 48000 i did like this : f = iExp / 48000. now there shows sth like a curve , but it dosn have the shape like Bell Curves . do you think there is sth wrong with my h(z) formula ? im using this formula :

Code: Select all

Y-Axisvalue = Complex.Abs(((b0 * z2) + (b1 * z) + b0) / (z2 + (a1 * z) + a2)) 


same as you posted earlier.
also hen i change the values for Q , F or G the curve shape changes to some strange shapes . am i using the correct way to calculate a0...b2 and also to calculate Y-Axisvalue ?
Actually i keep one by one the Y-Axisvalue to an array and later by using a for loop (0 to 600 ) draw point on the screen.

Post

Omega = 2 * PI * F0 * Fs
shouldn't that be 2*PI*F0/Fs?
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

Robin from www.rs-met.com wrote:
Omega = 2 * PI * F0 * Fs
shouldn't that be 2*PI*F0/Fs?
Yes but in here in the first of code i have initialize Fs to 1/48000 . is it that i still need to divide to Fs? cuz then f will be F0/48000 . how erver i have tried both but still haven get the correct result.

Post

Bluebirdglory wrote: Yes but in here in the first of code i have initialize Fs to 1/48000.
uh, bad coding practice. variable names should always be suggestive. if they are not, it's not good. but what is even worse is when they suggest something wrong. dunno about the language you use (what is it?), but in C++, 1/48000 would evaluate to zero because it would do an integer division.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

Robin from www.rs-met.com wrote:
Bluebirdglory wrote: Yes but in here in the first of code i have initialize Fs to 1/48000.
uh, bad coding practice. variable names should always be suggestive. if they are not, it's not good. but what is even worse is when they suggest something wrong. dunno about the language you use (what is it?), but in C++, 1/48000 would evaluate to zero because it would do an integer division.
Yes Sir I have changed them to standard type . :P . im still facing with problem in drawing this curve. is there any thing else wrong in here. thanks :)

Post

Bluebirdglory wrote:
Robin from www.rs-met.com wrote:
Bluebirdglory wrote: Yes but in here in the first of code i have initialize Fs to 1/48000.
uh, bad coding practice. variable names should always be suggestive. if they are not, it's not good. but what is even worse is when they suggest something wrong. dunno about the language you use (what is it?), but in C++, 1/48000 would evaluate to zero because it would do an integer division.
Yes Sir Thanks for the advice I have changed them to standard type . im still facing with problem in drawing this curve. is there any thing else wrong in here. thanks

Post

Hi every body!
Finally i could draw the curve :wink:
I directly calculated the magnitude respong based on the formula in PDF which "Robin" told me , but i calculated the a0..b2 by a formula which i found in a source code , i would like to share it in here :

Code: Select all

        w0 = Tan(PI * F0 / Fs)
        iden = 0.0
        w2 = w0 * w0

        Q = Q * (PI * F0 / Fs) / w0

        If gainDb <= 0.0 Then
            iden = 1.0 / (1.0 + (1.0 / Q * w0) + w2)

            b2 = iden * (1.0 - (gain / Q * w0) + w2)
            b1 = iden * 2.0 * (w2 - 1.0)
            b0 = iden * (1.0 + gain / Q * w0 + w2)

            a2 = iden * (1.0 - (1.0 / Q * w0) + w2)
            a1 = iden * 2.0 * (w2 - 1.0)

        Else

            iden = 1.0 / (1.0 + (gain / Q * w0) + w2)

            b2 = iden * (1.0 - (1.0 / Q * w0) + w2)
            b1 = iden * 2.0 * (w2 - 1.0)
            b0 = iden * (1.0 + (1.0 / Q * w0) + w2)

            a2 = iden * (1.0 - (gain / Q * w0) + w2)
            a1 = iden * 2.0 * (w2 - 1.0)
        End If
        a0 = 1.0
and i calculated the Y axis values by this codes :

Code: Select all

        For i As Integer = 0 To xAxis.Length - 1
            iExp = (10 * (10 ^ (i / 200)))
            yValue = 0.0

            w0 = 2 * PI * iExp / Fs
            cosW0 = Cos(w0)
            cos2W0 = Cos(2.0 * w0)

            num = (b0 ^ 2) + (b1 ^ 2) + (b2 ^ 2) + (2.0 * cosW0 * ((b0 * b1) + (b1 * b2))) + (2.0 * cos2W0 * b0 * b2)
            den = 1.0 + (a1 ^ 2) + (a2 ^ 2) + (2.0 * cosW0 * (a1 + (a1 * a2))) + (2.0 * cos2W0 * a2)

            y = (Abs(num / den))


            Graph.ptsArray(i).X = i
            Graph.ptsArray(i).Y = (10 * Log10(Abs(yValue)))
        Next i
It works correctly and i have checked the values (f1 , and f2 - bandwith ) to ensure it draws correctly.I dono where can i upload the codes , but if later on some one wanted do the same thing feel free to contact me : Bluebirdglory@yahoo.com.

Thanks alot to all of you specially "MDSP" and "Robin" for all the comment and helps :love:

Post Reply

Return to “DSP and Plugin Development”