Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

butterworth.h

Go to the documentation of this file.
00001 // 
00002 // author="Tony Kirke"
00003 // Copyright(c) 1993-1998 Tony Kirke
00004 /*
00005  * SPUC - Signal processing using C++ - A DSP library
00006  * 
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 #include <spuc.h>
00022 #include <complex.h>
00023 #include <iir_1st.h>
00024 #include <iir_2nd.h>
00025 namespace SPUC {
00033 
00034 
00035 
00036 template <class Numeric> class butterworth 
00037 {
00038         private:
00039         long order;
00040         long odd;
00041         long n2;
00042         complex<double>* roots;
00043         iir_2nd< Numeric>* iir;
00044         iir_1st< Numeric>* iir_1;
00045         double gain;
00046         double* coeff;
00047 
00048         public:
00052         butterworth(double fcd, long ord=1, double amax=3.0) {
00053                 // amax - attenuation at cutoff
00054                 gain = 1;
00055                 order = ord;
00056                 double epi = pow( (pow(10.0,(amax/10.)) - 1.0) ,(1./(2.0*ord)));
00057                 // fcd - desired cutoff frequency (normalized)
00058                 double wca = 2.0*tan(PI*fcd)/epi;
00059                 // wca - pre-warped angular frequency
00060             n2 = (order+1)/2;
00061                 odd = (order%2);
00062                 roots = new complex<double>[n2];
00063                 if (odd) iir_1 = new iir_1st< Numeric >;
00064                 get_roots(wca,order,n2);
00065                 bilinear(n2);
00066                 iir = new iir_2nd< Numeric >[order/2];
00067                 get_coeff(n2);
00068         }
00070         ~butterworth() {
00071           delete [] roots;
00072           if (odd) delete iir_1;
00073           delete [] iir;
00074         }
00076         void reset() {
00077           for (int j=odd;j<n2;j++) { 
00078                 iir[j-odd].reset();
00079                 if (odd) iir_1->reset();
00080           }
00081         } 
00083         void print() {
00084           for (int j=odd;j<n2;j++) { 
00085                 iir[j-odd].print();
00086           }
00087         } 
00089         Numeric clock(Numeric in) {
00090                 Numeric tmp = in;
00091                 for (int i=odd;i<n2;i++) {
00092                         tmp = iir[i-odd].clock(tmp);
00093                 }
00094                 if (odd) tmp = iir_1->clock(tmp);
00095                 return(gain*tmp);
00096         }
00097         private:
00099         void get_roots(double wp, long n, long n2) {
00100        long l = 0;
00101        if (n%2 == 0) l = 1;                                                 
00102            double arg;
00103            for (int j=0;j<n2;j++) {
00104                  arg = -0.5*PI*l/float(n);
00105                  roots[j] = wp*expj(arg);
00106                  l += 2;
00107           }
00108         }
00110         void bilinear(long n2) {
00111       double td;
00112           int j;
00113           const double a = 2.;
00114       if (odd) {
00115                 // For s-domain zero (or pole) at infinity we
00116                 // get z-domain zero (or pole) at z = -1
00117                 double tmp = (roots[0].real()-a)/(a+roots[0].real());
00118                 iir_1->set_coeff(-tmp);
00119                 gain *= 0.5*(1+tmp);
00120           }
00121       for (j=odd;j<n2;j++) {                       
00122                 td = a*a - 2*a*roots[j].real() + magsq(roots[j]);
00123                 roots[j] = complex<double>((a*a - magsq(roots[j])),
00124                                         2.0*a*roots[j].imag())/td;
00125           }
00126         }
00128         void get_coeff(long n2) {
00129         for (int j=odd;j<n2;j++) { 
00130                   iir[j-odd].set_coeff(-2*roots[j].real()/magsq(roots[j]),1.0/magsq(roots[j]));
00131                   gain *= (magsq(roots[j]) - 2*roots[j].real() + 1.0)/(4*magsq(roots[j])); 
00132           }
00133         }
00134 };
00135 } // namespace SPUC 

Generated on Fri Sep 16 11:02:25 2005 for spuc by  doxygen 1.4.4