1 /* -*- c++ -*- */
2 /*
3  * Copyright 2010,2012,2014 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 
23 #ifndef INCLUDED_FILTER_FFT_FILTER_H
24 #define INCLUDED_FILTER_FFT_FILTER_H
25 
26 #include <gnuradio/fft/fft.h>
27 #include <gnuradio/filter/api.h>
28 #include <gnuradio/gr_complex.h>
29 #include <vector>
30 
31 namespace gr {
32 namespace filter {
33 namespace kernel {
34 
35 /*!
36  * \brief Fast FFT filter with float input, float output and float taps
37  * \ingroup filter_blk
38  *
39  * \details
40  * This block performs fast convolution using the
41  * overlap-and-save algorithm. The filtering is performand in
42  * the frequency domain instead of the time domain (see
43  * gr::filter::kernel::fir_filter_fff). For an input signal x
44  * and filter coefficients (taps) t, we compute y as:
45  *
46  * \code
47  *    y = ifft(fft(x)*fft(t))
48  * \endcode
49  *
50  * This kernel computes the FFT of the taps when they are set to
51  * only perform this operation once. The FFT of the input signal
52  * x is done every time.
53  *
54  * Because this is designed as a very low-level kernel
55  * operation, it is designed for speed and avoids certain checks
56  * in the filter() function itself. The filter function expects
57  * that the input signal is a multiple of d_nsamples in the
58  * class that's computed internally to be as fast as
59  * possible. The function set_taps will return the value of
60  * nsamples that can be used externally to check this
61  * boundary. Notice that all implementations of the fft_filter
62  * GNU Radio blocks (e.g., gr::filter::fft_filter_fff) use this
63  * value of nsamples to compute the value to call
64  * gr::block::set_output_multiple that ensures the scheduler
65  * always passes this block the right number of samples.
66  */
67 class FILTER_API fft_filter_fff
68 {
69 private:
70     int d_ntaps;
71     int d_nsamples;
72     int d_fftsize; // fftsize = ntaps + nsamples - 1
73     int d_decimation;
74     fft::fft_real_fwd* d_fwdfft; // forward "plan"
75     fft::fft_real_rev* d_invfft; // inverse "plan"
76     int d_nthreads;              // number of FFTW threads to use
77     std::vector<float> d_tail;   // state carried between blocks for overlap-add
78     std::vector<float> d_taps;   // stores time domain taps
79     gr_complex* d_xformed_taps;  // Fourier xformed taps
80 
81     void compute_sizes(int ntaps);
tailsize()82     int tailsize() const { return d_ntaps - 1; }
83 
84 public:
85     /*!
86      * \brief Construct an FFT filter for float vectors with the given taps and decimation
87      * rate.
88      *
89      * This is the basic implementation for performing FFT filter for fast convolution
90      * in other blocks (e.g., gr::filter::fft_filter_fff).
91      *
92      * \param decimation The decimation rate of the filter (int)
93      * \param taps       The filter taps (vector of float)
94      * \param nthreads   The number of threads for the FFT to use (int)
95      */
96     fft_filter_fff(int decimation, const std::vector<float>& taps, int nthreads = 1);
97 
98     ~fft_filter_fff();
99 
100     /*!
101      * \brief Set new taps for the filter.
102      *
103      * Sets new taps and resets the class properties to handle different sizes
104      * \param taps       The filter taps (complex)
105      */
106     int set_taps(const std::vector<float>& taps);
107 
108     /*!
109      * \brief Set number of threads to use.
110      */
111     void set_nthreads(int n);
112 
113     /*!
114      * \brief Returns the taps.
115      */
116     std::vector<float> taps() const;
117 
118     /*!
119      * \brief Returns the number of taps in the filter.
120      */
121     unsigned int ntaps() const;
122 
123     /*!
124      * \brief Get number of threads being used.
125      */
126     int nthreads() const;
127 
128     /*!
129      * \brief Perform the filter operation
130      *
131      * \param nitems  The number of items to produce
132      * \param input   The input vector to be filtered
133      * \param output  The result of the filter operation
134      */
135     int filter(int nitems, const float* input, float* output);
136 };
137 
138 
139 /*!
140  * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
141  * \ingroup filter_blk
142  *
143  * \details
144  * This block performs fast convolution using the
145  * overlap-and-save algorithm. The filtering is performand in
146  * the frequency domain instead of the time domain (see
147  * gr::filter::kernel::fir_filter_ccc). For an input signal x
148  * and filter coefficients (taps) t, we compute y as:
149  *
150  * \code
151  *    y = ifft(fft(x)*fft(t))
152  * \endcode
153  *
154  * This kernel computes the FFT of the taps when they are set to
155  * only perform this operation once. The FFT of the input signal
156  * x is done every time.
157  *
158  * Because this is designed as a very low-level kernel
159  * operation, it is designed for speed and avoids certain checks
160  * in the filter() function itself. The filter function expects
161  * that the input signal is a multiple of d_nsamples in the
162  * class that's computed internally to be as fast as
163  * possible. The function set_taps will return the value of
164  * nsamples that can be used externally to check this
165  * boundary. Notice that all implementations of the fft_filter
166  * GNU Radio blocks (e.g., gr::filter::fft_filter_ccc) use this
167  * value of nsamples to compute the value to call
168  * gr::block::set_output_multiple that ensures the scheduler
169  * always passes this block the right number of samples.
170  */
171 class FILTER_API fft_filter_ccc
172 {
173 private:
174     int d_ntaps;
175     int d_nsamples;
176     int d_fftsize; // fftsize = ntaps + nsamples - 1
177     int d_decimation;
178     fft::fft_complex* d_fwdfft;     // forward "plan"
179     fft::fft_complex* d_invfft;     // inverse "plan"
180     int d_nthreads;                 // number of FFTW threads to use
181     std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add
182     std::vector<gr_complex> d_taps; // stores time domain taps
183     gr_complex* d_xformed_taps;     // Fourier xformed taps
184 
185     void compute_sizes(int ntaps);
tailsize()186     int tailsize() const { return d_ntaps - 1; }
187 
188 public:
189     /*!
190      * \brief Construct an FFT filter for complex vectors with the given taps and
191      * decimation rate.
192      *
193      * This is the basic implementation for performing FFT filter for fast convolution
194      * in other blocks (e.g., gr::filter::fft_filter_ccc).
195      *
196      * \param decimation The decimation rate of the filter (int)
197      * \param taps       The filter taps (vector of complex)
198      * \param nthreads   The number of threads for the FFT to use (int)
199      */
200     fft_filter_ccc(int decimation, const std::vector<gr_complex>& taps, int nthreads = 1);
201 
202     ~fft_filter_ccc();
203 
204     /*!
205      * \brief Set new taps for the filter.
206      *
207      * Sets new taps and resets the class properties to handle different sizes
208      * \param taps       The filter taps (complex)
209      */
210     int set_taps(const std::vector<gr_complex>& taps);
211 
212     /*!
213      * \brief Set number of threads to use.
214      */
215     void set_nthreads(int n);
216 
217     /*!
218      * \brief Returns the taps.
219      */
220     std::vector<gr_complex> taps() const;
221 
222     /*!
223      * \brief Returns the number of taps in the filter.
224      */
225     unsigned int ntaps() const;
226 
227     /*!
228      * \brief Get number of threads being used.
229      */
230     int nthreads() const;
231 
232     /*!
233      * \brief Perform the filter operation
234      *
235      * \param nitems  The number of items to produce
236      * \param input   The input vector to be filtered
237      * \param output  The result of the filter operation
238      */
239     int filter(int nitems, const gr_complex* input, gr_complex* output);
240 };
241 
242 
243 /*!
244  * \brief Fast FFT filter with gr_complex input, gr_complex output and float taps
245  * \ingroup filter_blk
246  *
247  * \details
248  * This block performs fast convolution using the
249  * overlap-and-save algorithm. The filtering is performand in
250  * the frequency domain instead of the time domain (see
251  * gr::filter::kernel::fir_filter_ccf). For an input signal x
252  * and filter coefficients (taps) t, we compute y as:
253  *
254  * \code
255  *    y = ifft(fft(x)*fft(t))
256  * \endcode
257  *
258  * This kernel computes the FFT of the taps when they are set to
259  * only perform this operation once. The FFT of the input signal
260  * x is done every time.
261  *
262  * Because this is designed as a very low-level kernel
263  * operation, it is designed for speed and avoids certain checks
264  * in the filter() function itself. The filter function expects
265  * that the input signal is a multiple of d_nsamples in the
266  * class that's computed internally to be as fast as
267  * possible. The function set_taps will return the value of
268  * nsamples that can be used externally to check this
269  * boundary. Notice that all implementations of the fft_filter
270  * GNU Radio blocks (e.g., gr::filter::fft_filter_ccf) use this
271  * value of nsamples to compute the value to call
272  * gr::block::set_output_multiple that ensures the scheduler
273  * always passes this block the right number of samples.
274  */
275 class FILTER_API fft_filter_ccf
276 {
277 private:
278     int d_ntaps;
279     int d_nsamples;
280     int d_fftsize; // fftsize = ntaps + nsamples - 1
281     int d_decimation;
282     fft::fft_complex* d_fwdfft;     // forward "plan"
283     fft::fft_complex* d_invfft;     // inverse "plan"
284     int d_nthreads;                 // number of FFTW threads to use
285     std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add
286     std::vector<float> d_taps;      // stores time domain taps
287     gr_complex* d_xformed_taps;     // Fourier xformed taps
288 
289     void compute_sizes(int ntaps);
tailsize()290     int tailsize() const { return d_ntaps - 1; }
291 
292 public:
293     /*!
294      * \brief Construct an FFT filter for complex vectors with the given taps and
295      * decimation rate.
296      *
297      * This is the basic implementation for performing FFT filter for fast convolution
298      * in other blocks (e.g., gr::filter::fft_filter_ccf).
299      *
300      * \param decimation The decimation rate of the filter (int)
301      * \param taps       The filter taps (float)
302      * \param nthreads   The number of threads for the FFT to use (int)
303      */
304     fft_filter_ccf(int decimation, const std::vector<float>& taps, int nthreads = 1);
305 
306     ~fft_filter_ccf();
307 
308     /*!
309      * \brief Set new taps for the filter.
310      *
311      * Sets new taps and resets the class properties to handle different sizes
312      * \param taps       The filter taps (complex)
313      */
314     int set_taps(const std::vector<float>& taps);
315 
316     /*!
317      * \brief Set number of threads to use.
318      */
319     void set_nthreads(int n);
320 
321     /*!
322      * \brief Returns the taps.
323      */
324     std::vector<float> taps() const;
325 
326     /*!
327      * \brief Returns the number of taps in the filter.
328      */
329     unsigned int ntaps() const;
330 
331     /*!
332      * \brief Returns the actual size of the filter.
333      *
334      * \details This value could be equal to ntaps, but we ofter
335      * build a longer filter to allow us to calculate a more
336      * efficient FFT. This value is the actual size of the filters
337      * used in the calculation of the overlap-and-save operation.
338      */
339     unsigned int filtersize() const;
340 
341     /*!
342      * \brief Get number of threads being used.
343      */
344     int nthreads() const;
345 
346     /*!
347      * \brief Perform the filter operation
348      *
349      * \param nitems  The number of items to produce
350      * \param input   The input vector to be filtered
351      * \param output  The result of the filter operation
352      */
353     int filter(int nitems, const gr_complex* input, gr_complex* output);
354 };
355 
356 } /* namespace kernel */
357 } /* namespace filter */
358 } /* namespace gr */
359 
360 #endif /* INCLUDED_FILTER_FFT_FILTER_H */
361