RTXI 1.3
plugins/include/DSP/bessfunc.cpp
Go to the documentation of this file.
00001 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00002 //
00003 //  File = bessfunc.cpp
00004 //
00005 //  Bessel Filter Function
00006 //
00007 
00008 #include <math.h>
00009 #include <stdlib.h>
00010 #include "bessfunc.h"
00011 #include "elipfunc.h"
00012 #include "laguerre.h"
00013 #include "complex.h"
00014 #include "cmpxpoly.h"
00015 #ifdef _DEBUG
00016 extern std::ofstream DebugFile;
00017 #endif
00018 
00019 //======================================================
00020 //  constructor
00021 
00022 BesselTransFunc::BesselTransFunc( int order, 
00023                                   double passband_edge,
00024                                   int norm_for_delay)
00025                 :FilterTransFunc(order)
00026 {
00027   int indx, indx_m1, indx_m2;
00028   int i, n, ii, work_order;
00029   double epsilon, epsilon2;
00030   int max_iter, laguerre_status;
00031   long q_poly[3][MAX_BESSEL_ORDER];
00032   complex *denom_poly, *work_coeff;
00033   complex root, work1, work2;
00034   double renorm_val, smallest;
00035   CmplxPolynomial *work_poly;
00036 
00037   //-------------------------------------------------------
00038   //  these values are reciprocals of values in Table 5.10
00039 
00040   double renorm_factor[9] = { 0.0,     0.0,     0.72675, 
00041                               0.57145, 0.46946, 0.41322, 
00042                               0.37038, 0.33898, 0.31546};
00043 
00044  Prototype_Pole_Locs = new complex[order+1];
00045  Num_Prototype_Poles = order;
00046  Prototype_Zero_Locs = new complex[1];
00047  Num_Prototype_Zeros = 0;
00048  
00049  H_Sub_Zero = 1.0;
00050   denom_poly = new complex[MAX_BESSEL_ORDER];
00051   work_coeff = new complex[MAX_BESSEL_ORDER];
00052 
00053   indx = 1;
00054   indx_m1 = 0;
00055   indx_m2 = 2;
00056   renorm_val = renorm_factor[order];
00057 
00058   //-----------------------------------------
00059   // initialize polynomials for n=0 and n=1
00060 
00061   for( i=0; i<(3*MAX_BESSEL_ORDER) ; i++) 
00062       q_poly[0][i] = 0;
00063 
00064   q_poly[0][0] = 1;
00065   q_poly[1][0] = 1;
00066   q_poly[1][1] = 1;
00067 
00068   //----------------------------------------------
00069   //  compute polynomial using recursion from n=2
00070   //  up through n=order
00071 
00072   for( n=2; n<=order; n++)
00073     {
00074     indx = (indx+1)%3;
00075     indx_m1 = (indx_m1+1)%3;
00076     indx_m2 = (indx_m2+1)%3;
00077 
00078     for( i=0; i<n; i++)
00079       {
00080       q_poly[indx][i] = (2*n-1) * 
00081                              q_poly[indx_m1][i];
00082       }
00083     for( i=2; i<=n; i++)
00084       {
00085       q_poly[indx][i] = q_poly[indx][i] + 
00086                              q_poly[indx_m2][i-2];
00087       }
00088     }
00089   if(norm_for_delay)
00090     {
00091     for( i=0; i<=order; i++)
00092       {
00093       denom_poly[i] = complex(
00094                       double(q_poly[indx][i]), 0.0);
00095       #ifdef _DEBUG
00096       DebugFile << "q_poly[" << i << "] = "
00097                 << q_poly[indx][i] << std::endl;
00098       #endif
00099       }
00100     }
00101   else
00102     {
00103     for( i=0; i<=order; i++)
00104       denom_poly[i] = complex(
00105                       (double(q_poly[indx][i]) * 
00106                       ipow(renorm_val, (order-i))), 0.0);
00107     }
00108   //---------------------------------------------------
00109   // use Laguerre method to find roots of the
00110   // denominator polynomial -- these roots are the
00111   // poles of the filter
00112 
00113   epsilon = 1.0e-6;
00114   epsilon2 = 1.0e-6;
00115   max_iter = 10;
00116 
00117   for(i=0; i<=order; i++) work_coeff[i] = denom_poly[i];
00118 
00119   for(i=order; i>1; i--)
00120     {
00121     root = complex(0.0,0.0);
00122     work_order = i;
00123     work_poly = new CmplxPolynomial( work_coeff, work_order);
00124     laguerre_status = LaguerreMethod( work_poly,
00125                                       &root,
00126                                       epsilon,
00127                                       epsilon2,
00128                                       max_iter);
00129     delete work_poly;
00130 
00131     #ifdef _DEBUG
00132     DebugFile << "laguerre_status = "
00133               << laguerre_status << std::endl;
00134     #endif
00135 
00136     if(laguerre_status <0)
00137       {
00138       #ifdef _DEBUG
00139       DebugFile << "FATAL ERROR - \n"
00140                 << "Laguerre method failed to converge.\n"
00141                 << "Unable to find poles for desired Bessel filter." 
00142                 << std::endl;
00143       #endif
00144       exit(-1);
00145       }
00146 
00147     #ifdef _DEBUG
00148     DebugFile << "root = " << root << std::endl;
00149     #endif
00150 
00151     //--------------------------------------------
00152     // if imaginary part of root is very small
00153     // relative to real part, set it to zero
00154 
00155     if(fabs(imag(root)) < epsilon*fabs(real(root)))
00156       {
00157       root = complex(real(root), 0.0);
00158       }
00159     Prototype_Pole_Locs[order+1-i] = root;
00160 
00161     //---------------------------------------------
00162     // deflate working polynomial by removing 
00163     // (s - r) factor where r is newly found root
00164 
00165     work1 = work_coeff[i];
00166     for(ii=i-1; ii>=0; ii--)
00167       {
00168       work2 = work_coeff[ii];
00169       work_coeff[ii] = work1;
00170       work1 = work2 + root * work1;
00171       }
00172     } // end of loop over i
00173   #ifdef _DEBUG
00174   DebugFile << "work_coeff[1] = " << work_coeff[1] << std::endl;
00175   DebugFile << "work_coeff[0] = " << work_coeff[0] << std::endl;
00176   #endif
00177   
00178   Prototype_Pole_Locs[order] = -work_coeff[0];
00179 
00180   #ifdef _DEBUG
00181   DebugFile << "pole[" << order << "] = "
00182             << Prototype_Pole_Locs[order] << std::endl;
00183   #endif
00184   //----------------------------------------------
00185   // sort poles so that imaginary parts are in
00186   // ascending order.  This order is critical for
00187   // sucessful operation of ImpulseResponse().
00188 
00189   for(i=1; i<order; i++)
00190     {
00191     smallest = imag(Prototype_Pole_Locs[i]);
00192     for( ii=i+1; ii<=order; ii++)
00193       {
00194       if(smallest <= imag(Prototype_Pole_Locs[ii])) continue;
00195         work1 = Prototype_Pole_Locs[ii];
00196         Prototype_Pole_Locs[ii] = Prototype_Pole_Locs[i];
00197         Prototype_Pole_Locs[i] = work1;
00198         smallest = imag(work1);
00199       }
00200     }
00201 
00202   #ifdef _DEBUG
00203   for(i=1; i<=order; i++)
00204     {
00205     DebugFile << "pole[" << i << "] = " 
00206               << Prototype_Pole_Locs[i] << std::endl;
00207     }
00208   #endif
00209 
00210   return;
00211 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines