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 2, 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}^{N} a_k y[n-k] = \sum_{k=0}^{M} b_k x[n-k]
49 * with the corresponding rational system function
52 H(z) = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} 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(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 () const { return d_fftaps.size (); }
86 * \brief install new taps.
88 void set_taps (const std::vector<tap_type> &fftaps,
89 const std::vector<tap_type> &fbtaps) throw (std::invalid_argument)
91 if (fftaps.size () != fbtaps.size ())
92 throw std::invalid_argument ("gri_iir::set_taps");
98 int n = fftaps.size ();
99 d_prev_input.resize (2 * n);
100 d_prev_output.resize (2 * n);
102 for (int i = 0; i < 2 * n; i++){
104 d_prev_output[i] = 0;
109 std::vector<tap_type> d_fftaps;
110 std::vector<tap_type> d_fbtaps;
112 std::vector<tap_type> d_prev_output;
113 std::vector<i_type> d_prev_input;
118 // general case. We may want to specialize this
120 template<class i_type, class o_type, class tap_type>
122 gri_iir<i_type, o_type, tap_type>::filter (const i_type input)
126 unsigned n = ntaps ();
131 int latest = d_latest;
133 acc = d_fftaps[0] * input;
134 for (i = 1; i < n; i ++)
135 acc += (d_fftaps[i] * d_prev_input[latest + i]
136 + d_fbtaps[i] * d_prev_output[latest + i]);
138 // store the values twice to avoid having to handle wrap-around in the loop
139 d_prev_output[latest] = acc;
140 d_prev_output[latest+n] = acc;
141 d_prev_input[latest] = input;
142 d_prev_input[latest+n] = input;
153 template<class i_type, class o_type, class tap_type>
155 gri_iir<i_type, o_type, tap_type>::filter_n (o_type output[],
156 const i_type input[],
159 for (int i = 0; i < n; i++)
160 output[i] = filter (input[i]);
163 #endif /* INCLUDED_GRI_IIR_H */