GNU Radio 3.6.1 C++ API
gr_single_pole_iir.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002,2006 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 #ifndef _GR_SINGLE_POLE_IIR_H_
23 #define _GR_SINGLE_POLE_IIR_H_
24 
25 #include <gr_core_api.h>
26 #include <stdexcept>
27 #include <gr_complex.h>
28 /*!
29  * \brief class template for single pole IIR filter
30  */
31 template<class o_type, class i_type, class tap_type>
33 public:
34  /*!
35  * \brief construct new single pole IIR with given alpha
36  *
37  * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
38  */
39  gr_single_pole_iir (tap_type alpha = 1.0)
40  {
41  d_prev_output = 0;
42  set_taps (alpha);
43  }
44 
45  /*!
46  * \brief compute a single output value.
47  * \returns the filtered input value.
48  */
49  o_type filter (const i_type input);
50 
51  /*!
52  * \brief compute an array of N output values.
53  * \p input must have n valid entries.
54  */
55  void filterN (o_type output[], const i_type input[], unsigned long n);
56 
57  /*!
58  * \brief install \p alpha as the current taps.
59  */
60  void set_taps (tap_type alpha)
61  {
62  if (alpha < 0 || alpha > 1)
63  throw std::out_of_range ("Alpha must be in [0, 1]\n");
64 
65  d_alpha = alpha;
66  d_one_minus_alpha = 1.0 - alpha;
67  }
68 
69  //! reset state to zero
70  void reset ()
71  {
72  d_prev_output = 0;
73  }
74 
75  o_type prev_output () const { return d_prev_output; }
76 
77 protected:
78  tap_type d_alpha;
80  o_type d_prev_output;
81 };
82 
83 
84 //
85 // general case. We may want to specialize this
86 //
87 template<class o_type, class i_type, class tap_type>
88 o_type
90 {
91  o_type output;
92 
93  output = d_alpha * input + d_one_minus_alpha * d_prev_output;
94  d_prev_output = output;
95 
96  return (o_type) output;
97 }
98 
99 
100 template<class o_type, class i_type, class tap_type>
101 void
103  const i_type input[],
104  unsigned long n)
105 {
106  for (unsigned i = 0; i < n; i++)
107  output[i] = filter (input[i]);
108 }
109 
110 
111 //
112 // Specialized case for gr_complex output and double taps
113 // We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double)
114 
115 template<class i_type>
116 class gr_single_pole_iir<gr_complex, i_type, double> {
117 public:
118  /*!
119  * \brief construct new single pole IIR with given alpha
120  *
121  * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i)
122  */
123  gr_single_pole_iir (double alpha = 1.0)
124  {
125  d_prev_output = 0;
126  set_taps (alpha);
127  }
128 
129  /*!
130  * \brief compute a single output value.
131  * \returns the filtered input value.
132  */
133  gr_complex filter (const i_type input);
134 
135  /*!
136  * \brief compute an array of N output values.
137  * \p input must have n valid entries.
138  */
139  void filterN (gr_complex output[], const i_type input[], unsigned long n);
140 
141  /*!
142  * \brief install \p alpha as the current taps.
143  */
144  void set_taps (double alpha)
145  {
146  if (alpha < 0 || alpha > 1)
147  throw std::out_of_range ("Alpha must be in [0, 1]\n");
148 
149  d_alpha = alpha;
150  d_one_minus_alpha = 1.0 - alpha;
151  }
152 
153  //! reset state to zero
154  void reset ()
155  {
156  d_prev_output = 0;
157  }
158 
159  gr_complexd prev_output () const { return d_prev_output; }
160 
161 protected:
162  double d_alpha;
165 };
166 
167 template< class i_type>
170 {
171  gr_complexd output;
172 
173  output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output;
174  d_prev_output = output;
175 
176  return (gr_complex) output;
177 }
178 
179 //Do we need to specialize this, although it is the same as the general case?
180 
181 template<class i_type>
182 void
184  const i_type input[],
185  unsigned long n)
186 {
187  for (unsigned i = 0; i < n; i++)
188  output[i] = filter (input[i]);
189 }
190 
191 #endif /* _GR_SINGLE_POLE_IIR_H_ */