GNU Radio 3.6.5 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2002,2006 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio 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 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 #ifndef _GR_SINGLE_POLE_IIR_H_ 00023 #define _GR_SINGLE_POLE_IIR_H_ 00024 00025 #include <gr_core_api.h> 00026 #include <stdexcept> 00027 #include <gr_complex.h> 00028 /*! 00029 * \brief class template for single pole IIR filter 00030 */ 00031 template<class o_type, class i_type, class tap_type> 00032 class gr_single_pole_iir { 00033 public: 00034 /*! 00035 * \brief construct new single pole IIR with given alpha 00036 * 00037 * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) 00038 */ 00039 gr_single_pole_iir (tap_type alpha = 1.0) 00040 { 00041 d_prev_output = 0; 00042 set_taps (alpha); 00043 } 00044 00045 /*! 00046 * \brief compute a single output value. 00047 * \returns the filtered input value. 00048 */ 00049 o_type filter (const i_type input); 00050 00051 /*! 00052 * \brief compute an array of N output values. 00053 * \p input must have n valid entries. 00054 */ 00055 void filterN (o_type output[], const i_type input[], unsigned long n); 00056 00057 /*! 00058 * \brief install \p alpha as the current taps. 00059 */ 00060 void set_taps (tap_type alpha) 00061 { 00062 if (alpha < 0 || alpha > 1) 00063 throw std::out_of_range ("Alpha must be in [0, 1]\n"); 00064 00065 d_alpha = alpha; 00066 d_one_minus_alpha = 1.0 - alpha; 00067 } 00068 00069 //! reset state to zero 00070 void reset () 00071 { 00072 d_prev_output = 0; 00073 } 00074 00075 o_type prev_output () const { return d_prev_output; } 00076 00077 protected: 00078 tap_type d_alpha; 00079 tap_type d_one_minus_alpha; 00080 o_type d_prev_output; 00081 }; 00082 00083 00084 // 00085 // general case. We may want to specialize this 00086 // 00087 template<class o_type, class i_type, class tap_type> 00088 o_type 00089 gr_single_pole_iir<o_type, i_type, tap_type>::filter (const i_type input) 00090 { 00091 o_type output; 00092 00093 output = d_alpha * input + d_one_minus_alpha * d_prev_output; 00094 d_prev_output = output; 00095 00096 return (o_type) output; 00097 } 00098 00099 00100 template<class o_type, class i_type, class tap_type> 00101 void 00102 gr_single_pole_iir<o_type, i_type, tap_type>::filterN (o_type output[], 00103 const i_type input[], 00104 unsigned long n) 00105 { 00106 for (unsigned i = 0; i < n; i++) 00107 output[i] = filter (input[i]); 00108 } 00109 00110 00111 // 00112 // Specialized case for gr_complex output and double taps 00113 // We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double) 00114 00115 template<class i_type> 00116 class gr_single_pole_iir<gr_complex, i_type, double> { 00117 public: 00118 /*! 00119 * \brief construct new single pole IIR with given alpha 00120 * 00121 * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) 00122 */ 00123 gr_single_pole_iir (double alpha = 1.0) 00124 { 00125 d_prev_output = 0; 00126 set_taps (alpha); 00127 } 00128 00129 /*! 00130 * \brief compute a single output value. 00131 * \returns the filtered input value. 00132 */ 00133 gr_complex filter (const i_type input); 00134 00135 /*! 00136 * \brief compute an array of N output values. 00137 * \p input must have n valid entries. 00138 */ 00139 void filterN (gr_complex output[], const i_type input[], unsigned long n); 00140 00141 /*! 00142 * \brief install \p alpha as the current taps. 00143 */ 00144 void set_taps (double alpha) 00145 { 00146 if (alpha < 0 || alpha > 1) 00147 throw std::out_of_range ("Alpha must be in [0, 1]\n"); 00148 00149 d_alpha = alpha; 00150 d_one_minus_alpha = 1.0 - alpha; 00151 } 00152 00153 //! reset state to zero 00154 void reset () 00155 { 00156 d_prev_output = 0; 00157 } 00158 00159 gr_complexd prev_output () const { return d_prev_output; } 00160 00161 protected: 00162 double d_alpha; 00163 double d_one_minus_alpha; 00164 gr_complexd d_prev_output; 00165 }; 00166 00167 template< class i_type> 00168 gr_complex 00169 gr_single_pole_iir<gr_complex, i_type, double>::filter (const i_type input) 00170 { 00171 gr_complexd output; 00172 00173 output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output; 00174 d_prev_output = output; 00175 00176 return (gr_complex) output; 00177 } 00178 00179 //Do we need to specialize this, although it is the same as the general case? 00180 00181 template<class i_type> 00182 void 00183 gr_single_pole_iir<gr_complex, i_type, double>::filterN (gr_complex output[], 00184 const i_type input[], 00185 unsigned long n) 00186 { 00187 for (unsigned i = 0; i < n; i++) 00188 output[i] = filter (input[i]); 00189 } 00190 00191 #endif /* _GR_SINGLE_POLE_IIR_H_ */