bpmdsp/create_resonator_representation.c

Go to the documentation of this file.
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   // allocate memory for the filterrepresentation...
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   // for all : 
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     // negative Q, so assume infinte Q : pure oscillator, calculate the poles
00040     z = c_exp( complex(0., theta) );
00041     zrep->pole[0] = z;
00042     zrep->pole[1] = c_conj( z );
00043   } else {
00044     // finite Q factor for the resonator, calculate the poles
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   // adjust the zeros for a bandstop resonator
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   // adjust the zeros for an allpas resonator
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 }

Generated on Thu Jan 10 10:18:04 2008 for libbpm by  doxygen 1.5.1