00001
00005 #include "bpm/bpm_dsp.h"
00006
00007
00008 complex_t _reflect(complex_t z) {
00009 double r = c_abs(z);
00010 return c_div( z, complex( r*r, 0. ) );
00011 }
00012
00013
00014
00015 filterrep_t* create_resonator_representation( filter_t *f ) {
00016
00017 double theta, r, thm, th1, th2, phi;
00018 int i, cvg;
00019 complex_t z, g;
00020 complex_t topco[MAXPZ+1], botco[MAXPZ+1];
00021 filterrep_t *zrep;
00022
00023
00024 zrep = (filterrep_t*) calloc( 1, sizeof( filterrep_t) );
00025
00026 if ( ! r ) {
00027 bpm_error( "Cannot allocate memory for resonator representation.", __FILE__, __LINE__ );
00028 return NULL;
00029 }
00030
00031
00032 zrep->nzeros = 2;
00033 zrep->npoles = 2;
00034 zrep->zero[0] = complex( 1., 0. );
00035 zrep->zero[1] = complex( -1., 0. );
00036 theta = 2.*PI*f->alpha1;
00037
00038 if ( f->Q <= 0. ) {
00039
00040 z = c_exp( complex(0., theta) );
00041 zrep->pole[0] = z;
00042 zrep->pole[1] = c_conj( z );
00043 } else {
00044
00045 _expand_complex_polynomial( zrep->zero, zrep->nzeros, topco);
00046 r = exp(-theta / (2.0 * f->Q));
00047 thm = theta;
00048 th1 = 0.0;
00049 th2 = PI;
00050 cvg = 0;
00051 for ( i=0; ( i<MAX_RESONATOR_ITER ) && ( cvg == 0 ); i++ ) {
00052 z = complex( r*cos(thm), r*sin(thm));
00053 zrep->pole[0] = z;
00054 zrep->pole[1] = c_conj(z);
00055
00056 _expand_complex_polynomial( zrep->pole, zrep->npoles, botco);
00057
00058 g = c_div( _eval_complex_polynomial( topco, zrep->nzeros, complex(cos(theta),sin(theta))),
00059 _eval_complex_polynomial( botco, zrep->npoles, complex(cos(theta),sin(theta))) );
00060 phi = g.im / g.re;
00061 if ( phi > 0.0 ) th2 = thm; else th1 = thm;
00062 if ( fabs(phi) < FILT_EPS ) cvg = 1;
00063 thm = 0.5 * ( th1 + th2 );
00064 }
00065 if ( ! cvg ) {
00066 bpm_error( "Finite Q resonator failed to converge on pole/zero calculation.",
00067 __FILE__, __LINE__ );
00068 free(zrep);
00069 return NULL;
00070 }
00071
00072 }
00073
00074
00075
00076 if ( f->options & BANDSTOP ) {
00077 theta = 2.*PI*f->alpha1;
00078 z = complex( cos(theta), sin(theta) );
00079 zrep->zero[0] = z;
00080 zrep->zero[1] = c_conj( z );
00081 }
00082
00083
00084 if ( f->options & ALLPASS ) {
00085 zrep->zero[0] = _reflect( zrep->pole[0] );
00086 zrep->zero[1] = _reflect( zrep->pole[1] );
00087 }
00088
00089
00090 return zrep;
00091 }