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