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