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