hhmm... well... that may even out some of the errors. but why not just use the exact value as given by the closed form formula (which is also presumably much easier and faster to evaluate)?thevinn wrote:I've switched over to taking the average of the sum of the absolute values of the samples as the magnitude ("a"). It incorporates every sample. I also compute this for the original sine wave ("a0") for the formula
Code: Select all
dB = 20 * log ( a / a0 )
Taking another crack at basic filtering
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Because I don't know which formula. Is it on www.rs-met.com ? Which formula is it?Robin from www.rs-met.com wrote:why not just use the exact value as given by the closed form formula (which is also presumably much easier and faster to evaluate)?
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
-6dB = half amplitude, -3dB = half powerthevinn wrote:In my formula I am using -6dB = half power (i.e. 20*log(a/a0)).
wott? a bug in the RBJ formulas as published in:The orange line is a low pass Biquad. I've checked and triple checked the coefficients (even found a bug in an online published version of the cookbook).
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
i'm using these formulas since ages without any problems.
that's a bit much. i'd expect -3 dB but i'm not quite sure at the moment if the RBJ filters adhere to this convention ...the Q/resonance stuff makes things more complicated. i think, at Q=1/sqrt(2) it should be at -3 dB at the cutoff. but not entirely sure.Is ~20dB drop at the cut-off frequency the expected result from a second order biquad lowpass?
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
I'm starting to wonder if getBiquadMagnitudeAt() is the right formula.
I found this other equation from http://groups.google.com/group/comp.dsp ... 63ac56b686 and I implemented it:
It gives me different results. The shape of the curve is the same, but the cutoff frequency is closer to where I would expect it to be. But still not where it should be (I think).
I found this other equation from http://groups.google.com/group/comp.dsp ... 63ac56b686 and I implemented it:
Code: Select all
double getBiquadMagnitudeAt2( double b0, double b1, double b2, double a0, double a1, double a2, double normalizedFrequency )
{
double a, b;
double phi;
phi=sin(M_2_PI*normalizedFrequency);
phi=phi*phi;
a=(::pow(b0+b1+b2, 2.0)-4*(b0*b1+4*b0*b2+b1*b2)*phi+16*b0*b2*phi*phi);
b=(::pow(a0+a1+a2, 2.0)-4*(a0*a1+4*a0*a2+a1*a2)*phi+16*a0*a2*phi*phi);
return a/b;
}- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
That one is fine but the original PDF has an error in the C-code example:Robin from www.rs-met.com wrote:http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
i'm using these formulas since ages without any problems.
http://music.ucsd.edu/~tre/biquad.pdf
For case LP (lowpass) they are setting
Code: Select all
a2 = alpha - 1.0F-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
for a biquad it would be the getBiquadMagnitudeAt function as posted here. for other filters, similar formulas can be worked out. for the 1st order filter, you find them in my pdf (posted here). for the general case of a direct form filter, there's a formula with finite sums in the numerator and denominator which i currently don't have handy.thevinn wrote:Because I don't know which formula. Is it on www.rs-met.com ? Which formula is it?Robin from www.rs-met.com wrote:why not just use the exact value as given by the closed form formula (which is also presumably much easier and faster to evaluate)?
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Oh..I thought you were referring to the function that computes the magnitude response from a given buffer of samples.Robin from www.rs-met.com wrote:for a biquad it would be the getBiquadMagnitudeAt function as posted here.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
the more i think about it, the wronger this approach appears to me. think about an allpass that shifts your sinusoid by a fractional amount of samples. that will certainly alter the the maximum absolute value and quite probably also the average. if you really need a method for measuring frequency responses of filters that are a black box to you, i'd recommend to stick to the FFT of the impulse responsethevinn wrote:Oh..I thought you were referring to the function that computes the magnitude response from a given buffer of samples.Robin from www.rs-met.com wrote:for a biquad it would be the getBiquadMagnitudeAt function as posted here.
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
I'm completely exhausted from these efforts. I'm going to rebuild my self-esteem by implementing some more easy (and necessary) features while I recover. I didn't want to start with the FFT so soon but it seems to be the best option now. I will revisit this topic in the future and try the FFT approach.Robin from www.rs-met.com wrote:if you really need a method for measuring frequency responses of filters that are a black box to you, i'd recommend to stick to the FFT of the impulse response
In the meanwhile, thanks to everyone for their help. Using what I learned I was able to find a bug in my high pass filter, and tweak my equalizer so it produces the results I was looking for from the start (Re: "totally awesome cplusplus DSP code"). My bipolar filter is also improved, and the sliders and knobs feel more useful now with new decibel->gain mappings.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
you probably don't want to implement your own FFT then and you don't have to. there are good libraries out there. ooura, kiss-fft, FFTReal (i think), stephan bernsee's and probably others as well. good luck.thevinn wrote:I'm completely exhausted from these efforts. I'm going to rebuild my self-esteem by implementing some more easy (and necessary) features while I recover. I didn't want to start with the FFT so soon but it seems to be the best option now. I will revisit this topic in the future and try the FFT approach.
-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
...update: i digged out the formula for the magnitude (and phase) response for the general direct form filter and updated the pdf document accordingly:Robin from www.rs-met.com wrote:...for the general case of a direct form filter, there's a formula with finite sums in the numerator and denominator which i currently don't have handy...
www.rs-met.com/documents/dsp/BasicDigitalFilters.pdf
also, in order to assure correctness, i implemented it in a small matlab/octave function:
Code: Select all
function [m p] = directFormMagnitudeAndPhaseAt(b, a, w);
% Returns the value of the magnitude- and phase-response at the normalized
% radian frequency w (w = 2*pi*frequency/sampleRate) of the direct form
% filter defined by the filter coefficient vectors b and a with the
% difference equation:
%
% y[n] = b[1] x[n] + b2 x[n-1] + ... - a[2] y[n-1] - a[3] y[n-2] - ...
%
% usage:
% [m p] = directFormMagnitudeAndPhaseAt(b, a, w);
%
% input-variables:
% -b: vector of the feedforward coefficients
% -a: vector of the feedback coefficients
% -w: normalized radian frequency w
% (w = 2*pi*frequency/sampleRate) at which the magnitude
% response id to be evaluated
%
% output-variables:
% -m: value of the magnitude response at the given w
% -p: value of the phase response at the given w
%--------------------------------------------------------------------------
M = length(b);
sb = 0;
cb = 0;
for k=0:M-1
sb = sb + b(k+1) * sin(k*w);
cb = cb + b(k+1) * cos(k*w);
end
N = length(a);
sa = 0;
ca = 1;
for k=1:N-1
sa = sa + a(k+1) * sin(k*w);
ca = ca + a(k+1) * cos(k*w);
end
m = sqrt( (cb^2+sb^2) / (ca^2+sa^2) );
p = atan2(sb,cb) - atan2(sa,ca);
% wrap phase into range -pi...pi
if p > pi
p = p-2*pi;
elseif p < -pi
p = p+2*pi;
end-
Music Engineer Music Engineer https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=15959
- KVRAF
- 4379 posts since 8 Mar, 2004 from Berlin, Germany
wait...there seems to be a sign inversion error with the phase response...i'll have to investigate this...
-
- KVRer
- 11 posts since 25 Jun, 2009 from Malaysia
May i know if we want the formula for higher orders,( 3 or 4 ) how the formula will be ? thanksRobin from www.rs-met.com wrote:O.K. here's some pdf where i noted down the formulas for the magnitude responses of some low order filtersin the meanwhile i'll try to dig out the formulas....
www.rs-met.com/documents/dsp/BasicDigitalFilters.pdf
here's the corresponding C++ code for the biquad:
Code: Select all
double getBiquadMagnitudeAt(double b0, double b1, double b2, double a1, double a2, double omega) { double cosOmega = cos(omega); double cos2Omega = cos(2.0*omega); double num = b0*b0 + b1*b1 + b2*b2 + 2.0*cosOmega*(b0*b1 + b1*b2) + 2.0*cos2Omega*b0*b2; double den = 1.0 + a1*a1 + a2*a2 + 2.0*cosOmega*(a1 + a1*a2) + 2.0*cos2Omega*a2; return sqrt(num/den); }
- KVRian
- Topic Starter
- 775 posts since 30 Nov, 2008
Full source code for what you ask, and much much more:Bluebirdglory wrote:May i know if we want the formula for higher orders,( 3 or 4 ) how the formula will be ? thanks
http://code.google.com/p/dspfilterscpp/
The function you are looking for is called Response(). Use one of the predefined filters, or load a cascade with your own coefficients and then call Response() to get the complex-valued response at angular frequency w. From there you can use abs() to get the magnitude response and phase() to get the phase response.
