3 * Copyright 2002 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
23 #ifndef INCLUDED_GRI_IIR_H
24 #define INCLUDED_GRI_IIR_H
30 * \brief base class template for Infinite Impulse Response filter (IIR)
32 template<class i_type, class o_type, class tap_type>
36 * \brief Construct an IIR with the given taps.
38 * This filter uses the Direct Form I implementation, where
39 * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones.
41 * \p fftaps and \p fbtaps must have equal numbers of taps
43 * The input and output satisfy a difference equation of the form
46 y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k]
49 * with the corresponding rational system function
52 H(z) = \frac{\sum_{k=0}^{N} b_k z^{-k}}{1 - \sum_{k=1}^{M} a_k z^{-k}}
55 * Note that some texts define the system function with a + in the denominator.
56 * If you're using that convention, you'll need to negate the feedback taps.
58 gri_iir (const std::vector<tap_type>& fftaps,
59 const std::vector<tap_type>& fbtaps) throw (std::invalid_argument)
61 set_taps (fftaps, fbtaps);
64 gri_iir () : d_latest_n(0),d_latest_m(0) { }
69 * \brief compute a single output value.
70 * \returns the filtered input value.
72 o_type filter (const i_type input);
75 * \brief compute an array of N output values.
76 * \p input must have N valid entries.
78 void filter_n (o_type output[], const i_type input[], long n);
81 * \return number of taps in filter.
83 unsigned ntaps_ff () const { return d_fftaps.size (); }
84 unsigned ntaps_fb () const { return d_fbtaps.size (); }
87 * \brief install new taps.
89 void set_taps (const std::vector<tap_type> &fftaps,
90 const std::vector<tap_type> &fbtaps) throw (std::invalid_argument)
99 int n = fftaps.size ();
100 int m = fbtaps.size ();
101 d_prev_input.resize (2 * n);
102 d_prev_output.resize (2 * m);
104 for (int i = 0; i < 2 * n; i++){
107 for (int i = 0; i < 2 * m; i++){
108 d_prev_output[i] = 0;
113 std::vector<tap_type> d_fftaps;
114 std::vector<tap_type> d_fbtaps;
117 std::vector<tap_type> d_prev_output;
118 std::vector<i_type> d_prev_input;
123 // general case. We may want to specialize this
125 template<class i_type, class o_type, class tap_type>
127 gri_iir<i_type, o_type, tap_type>::filter (const i_type input)
131 unsigned n = ntaps_ff ();
132 unsigned m = ntaps_fb ();
137 int latest_n = d_latest_n;
138 int latest_m = d_latest_m;
140 acc = d_fftaps[0] * input;
141 for (i = 1; i < n; i ++)
142 acc += (d_fftaps[i] * d_prev_input[latest_n + i]);
143 for (i = 1; i < m; i ++)
144 acc += (d_fbtaps[i] * d_prev_output[latest_m + i]);
146 // store the values twice to avoid having to handle wrap-around in the loop
147 d_prev_output[latest_m] = acc;
148 d_prev_output[latest_m+m] = acc;
149 d_prev_input[latest_n] = input;
150 d_prev_input[latest_n+n] = input;
159 d_latest_m = latest_m;
160 d_latest_n = latest_n;
165 template<class i_type, class o_type, class tap_type>
167 gri_iir<i_type, o_type, tap_type>::filter_n (o_type output[],
168 const i_type input[],
171 for (int i = 0; i < n; i++)
172 output[i] = filter (input[i]);
175 #endif /* INCLUDED_GRI_IIR_H */