diff options
57 files changed, 477 insertions, 1080 deletions
diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc index 0efc890715..5c4b3ef10b 100644 --- a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc @@ -1041,7 +1041,7 @@ dvbt_reference_signals_impl::dvbt_reference_signals_impl( d_pg(config), d_ninput(ninput), d_noutput(noutput), - ofdm_fft(config.d_transmission_mode == T2k ? 2048 : 8192, false, 1), + ofdm_fft(config.d_transmission_mode == T2k ? 2048 : 8192, 1), ofdm_fft_size(config.d_transmission_mode == T2k ? 2048 : 8192), normalization(1.0 / std::sqrt(27.0 * config.d_payload_length)) { diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h index dc271a6503..3e44c872da 100644 --- a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h +++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h @@ -231,7 +231,7 @@ private: int d_ninput; int d_noutput; - fft::fft_complex ofdm_fft; + fft::fft_complex_rev ofdm_fft; int ofdm_fft_size; float normalization; diff --git a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc index 3025113d1c..fca5fde267 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc +++ b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc @@ -57,7 +57,7 @@ dvbt2_p1insertion_cc_impl::dvbt2_p1insertion_cc_impl(dvbt2_extended_carrier_t ca real_negative_threshold_count(0), imag_positive_threshold_count(0), imag_negative_threshold_count(0), - p1_fft(1024, false, 1) + p1_fft(1024, 1) { int s1, s2, index = 0; int p1_fft_size = 1024; diff --git a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h index 47006c705e..09a06ce279 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h +++ b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h @@ -45,7 +45,7 @@ private: int imag_positive_threshold_count; int imag_negative_threshold_count; - fft::fft_complex p1_fft; + fft::fft_complex_rev p1_fft; const static int p1_active_carriers[384]; const static unsigned char s1_modulation_patterns[8][8]; diff --git a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc index adf4821d47..0481222f3b 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc +++ b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc @@ -62,8 +62,8 @@ dvbt2_paprtr_cc_impl::dvbt2_paprtr_cc_impl(dvbt2_extended_carrier_t carriermode, : gr::sync_block("dvbt2_paprtr_cc", gr::io_signature::make(1, 1, sizeof(gr_complex) * vlength), gr::io_signature::make(1, 1, sizeof(gr_complex) * vlength)), + papr_fft(vlength, 1), papr_fft_size(vlength), - papr_fft(vlength, false, 1), fft_size(fftsize), carrier_mode(carriermode), papr_mode(paprmode), diff --git a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h index 372af6e935..8910a5c16c 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h +++ b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h @@ -33,9 +33,8 @@ namespace dtv { class dvbt2_paprtr_cc_impl : public dvbt2_paprtr_cc { private: - const int papr_fft_size; - fft::fft_complex papr_fft; - + fft::fft_complex_rev papr_fft; + int papr_fft_size; int num_symbols; int fft_size; int left_nulls; diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc index 188821abce..018f052e46 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc +++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc @@ -70,7 +70,7 @@ dvbt2_pilotgenerator_cc_impl::dvbt2_pilotgenerator_cc_impl( carrier_mode(carriermode), papr_mode(paprmode), equalization_enable(equalization), - ofdm_fft(vlength, false, 1), + ofdm_fft(vlength, 1), ofdm_fft_size(vlength) { int step, ki; diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h index b5b851b2f8..58473ed7f2 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h +++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h @@ -73,7 +73,7 @@ private: void init_prbs(void); void init_pilots(void); - fft::fft_complex ofdm_fft; + fft::fft_complex_rev ofdm_fft; int ofdm_fft_size; const static unsigned char pn_sequence_table[CHIPS / 8]; diff --git a/gr-fft/grc/fft_fft_vxx.block.yml b/gr-fft/grc/fft_fft_vxx.block.yml index ce30078b9b..9ced5636b8 100644 --- a/gr-fft/grc/fft_fft_vxx.block.yml +++ b/gr-fft/grc/fft_fft_vxx.block.yml @@ -28,7 +28,6 @@ parameters: dtype: enum options: ['True', 'False'] option_labels: ['Yes', 'No'] - hide: ${ 'all' if type == 'float' else 'none' } - id: nthreads label: Num. Threads dtype: int @@ -52,7 +51,7 @@ templates: % if type == "complex": fft.fft_vcc(${fft_size}, ${forward}, ${window}, ${shift}, ${nthreads}) % else: - fft.fft_vfc(${fft_size}, ${forward}, ${window}, ${nthreads}) + fft.fft_vfc(${fft_size}, ${forward}, ${window}, ${shift}, ${nthreads}) % endif callbacks: - set_nthreads(${nthreads}) @@ -64,7 +63,7 @@ cpp_templates: % if type == "complex": this->${id} = fft::fft_vcc::make(${fft_size}, ${forward}, ${window}, ${shift}, ${nthreads}); % else: - this->${id} = fft::fft_vfc::make(${fft_size}, ${forward}, ${window}, ${nthreads}); + this->${id} = fft::fft_vfc::make(${fft_size}, ${forward}, ${window}, ${shift}, ${nthreads}); % endif link: ['gnuradio-fft'] callbacks: diff --git a/gr-fft/include/gnuradio/fft/CMakeLists.txt b/gr-fft/include/gnuradio/fft/CMakeLists.txt index 43698bdd44..e3f6275204 100644 --- a/gr-fft/include/gnuradio/fft/CMakeLists.txt +++ b/gr-fft/include/gnuradio/fft/CMakeLists.txt @@ -12,8 +12,7 @@ install(FILES api.h fft.h fft_shift.h - fft_vcc.h - fft_vfc.h + fft_v.h goertzel.h goertzel_fc.h window.h diff --git a/gr-fft/include/gnuradio/fft/fft.h b/gr-fft/include/gnuradio/fft/fft.h index cc47a4f169..6163d2f83f 100644 --- a/gr-fft/include/gnuradio/fft/fft.h +++ b/gr-fft/include/gnuradio/fft/fft.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2008,2012 Free Software Foundation, Inc. + * Copyright 2003,2008,2012,2020 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -38,135 +38,65 @@ public: static boost::mutex& mutex(); }; -/*! - * \brief FFT: complex in, complex out - * \ingroup misc - */ -class FFT_API fft_complex -{ - int d_nthreads; - volk::vector<gr_complex> d_inbuf; - volk::vector<gr_complex> d_outbuf; - void* d_plan; - gr::logger_ptr d_logger; - gr::logger_ptr d_debug_logger; - -public: - fft_complex(int fft_size, bool forward = true, int nthreads = 1); - // Copy disabled due to d_plan. - fft_complex(const fft_complex&) = delete; - fft_complex& operator=(const fft_complex&) = delete; - virtual ~fft_complex(); - - /* - * These return pointers to buffers owned by fft_impl_fft_complex - * into which input and output take place. It's done this way in - * order to ensure optimal alignment for SIMD instructions. - */ - gr_complex* get_inbuf() { return d_inbuf.data(); } - gr_complex* get_outbuf() { return d_outbuf.data(); } - - int inbuf_length() const { return d_inbuf.size(); } - int outbuf_length() const { return d_outbuf.size(); } - - /*! - * Set the number of threads to use for calculation. - */ - void set_nthreads(int n); - - /*! - * Get the number of threads being used by FFTW - */ - int nthreads() const { return d_nthreads; } - - /*! - * compute FFT. The input comes from inbuf, the output is placed in - * outbuf. - */ - void execute(); -}; /*! - * \brief FFT: real in, complex out - * \ingroup misc + \brief FFT: templated + \ingroup misc */ -class FFT_API fft_real_fwd -{ - int d_nthreads; - volk::vector<float> d_inbuf; - volk::vector<gr_complex> d_outbuf; - void* d_plan; - gr::logger_ptr d_logger; - gr::logger_ptr d_debug_logger; -public: - fft_real_fwd(int fft_size, int nthreads = 1); - // Copy disabled due to d_plan. - fft_real_fwd(const fft_real_fwd&) = delete; - fft_real_fwd& operator=(const fft_real_fwd&) = delete; - virtual ~fft_real_fwd(); - /* - * These return pointers to buffers owned by fft_impl_fft_real_fwd - * into which input and output take place. It's done this way in - * order to ensure optimal alignment for SIMD instructions. - */ - float* get_inbuf() { return d_inbuf.data(); } - gr_complex* get_outbuf() { return d_outbuf.data(); } +template <class T, bool forward> +struct fft_inbuf { + typedef T type; +}; - int inbuf_length() const { return d_inbuf.size(); } - int outbuf_length() const { return d_outbuf.size(); } +template <> +struct fft_inbuf<float, false> { + typedef gr_complex type; +}; - /*! - * Set the number of threads to use for caclulation. - */ - void set_nthreads(int n); - /*! - * Get the number of threads being used by FFTW - */ - int nthreads() const { return d_nthreads; } +template <class T, bool forward> +struct fft_outbuf { + typedef T type; +}; - /*! - * compute FFT. The input comes from inbuf, the output is placed in - * outbuf. - */ - void execute(); +template <> +struct fft_outbuf<float, true> { + typedef gr_complex type; }; -/*! - * \brief FFT: complex in, float out - * \ingroup misc - */ -class FFT_API fft_real_rev +template <class T, bool forward> +class FFT_API fft { int d_nthreads; - volk::vector<gr_complex> d_inbuf; - volk::vector<float> d_outbuf; + volk::vector<typename fft_inbuf<T, forward>::type> d_inbuf; + volk::vector<typename fft_outbuf<T, forward>::type> d_outbuf; void* d_plan; gr::logger_ptr d_logger; gr::logger_ptr d_debug_logger; + void initialize_plan(int fft_size); public: - fft_real_rev(int fft_size, int nthreads = 1); + fft(int fft_size, int nthreads = 1); // Copy disabled due to d_plan. - fft_real_rev(const fft_real_rev&) = delete; - fft_real_rev& operator=(const fft_real_rev&) = delete; - virtual ~fft_real_rev(); + fft(const fft&) = delete; + fft& operator=(const fft&) = delete; + virtual ~fft(); /* - * These return pointers to buffers owned by fft_impl_fft_real_rev + * These return pointers to buffers owned by fft_impl_fft_complex * into which input and output take place. It's done this way in * order to ensure optimal alignment for SIMD instructions. */ - gr_complex* get_inbuf() { return d_inbuf.data(); } - float* get_outbuf() { return d_outbuf.data(); } + typename fft_inbuf<T, forward>::type* get_inbuf() { return d_inbuf.data(); } + typename fft_outbuf<T, forward>::type* get_outbuf() { return d_outbuf.data(); } int inbuf_length() const { return d_inbuf.size(); } int outbuf_length() const { return d_outbuf.size(); } /*! - * Set the number of threads to use for caclulation. + * Set the number of threads to use for calculation. */ void set_nthreads(int n); @@ -182,6 +112,11 @@ public: void execute(); }; +using fft_complex_fwd = fft<gr_complex, true>; +using fft_complex_rev = fft<gr_complex, false>; +using fft_real_fwd = fft<float, true>; +using fft_real_rev = fft<float, false>; + } /* namespace fft */ } /*namespace gr */ diff --git a/gr-fft/include/gnuradio/fft/fft_vcc.h b/gr-fft/include/gnuradio/fft/fft_v.h index 95d1f18553..8fe4dba37e 100644 --- a/gr-fft/include/gnuradio/fft/fft_vcc.h +++ b/gr-fft/include/gnuradio/fft/fft_v.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2007,2008,2012,2018 Free Software Foundation, Inc. + * Copyright 2004,2007,2008,2012,2018,2020 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -8,8 +8,8 @@ * */ -#ifndef INCLUDED_FFT_FFT_VCC_H -#define INCLUDED_FFT_FFT_VCC_H +#ifndef INCLUDED_FFT_FFT_V_H +#define INCLUDED_FFT_FFT_V_H #include <gnuradio/fft/api.h> #include <gnuradio/sync_block.h> @@ -44,20 +44,18 @@ namespace fft { * * \see http://www.fftw.org/faq/section3.html#whyscaled */ -class FFT_API fft_vcc : virtual public sync_block +template <class T, bool forward> +class FFT_API fft_v : virtual public sync_block { public: - // gr::fft::fft_vcc::sptr - typedef std::shared_ptr<fft_vcc> sptr; + typedef std::shared_ptr<fft_v<T, forward>> sptr; /*! \brief * \param[in] fft_size N. - * \param[in] forward True performs FFT, False performs IFFT. * \param[in] window Window function to be used. * \param[in] shift True moves DC carrier to the middle. * \param[in] nthreads Number of underlying threads. */ static sptr make(int fft_size, - bool forward, const std::vector<float>& window, bool shift = false, int nthreads = 1); @@ -72,4 +70,4 @@ public: } /* namespace fft */ } /* namespace gr */ -#endif /* INCLUDED_FFT_FFT_VCC_H */ +#endif /* INCLUDED_FFT_FFT_V_H */ diff --git a/gr-fft/include/gnuradio/fft/fft_vfc.h b/gr-fft/include/gnuradio/fft/fft_vfc.h deleted file mode 100644 index 21859abe17..0000000000 --- a/gr-fft/include/gnuradio/fft/fft_vfc.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010,2012,2018 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifndef INCLUDED_FFT_FFT_VFC_H -#define INCLUDED_FFT_FFT_VFC_H - -#include <gnuradio/fft/api.h> -#include <gnuradio/sync_block.h> - -namespace gr { -namespace fft { - -/*! - * \brief Compute forward or reverse FFT. complex vector in / complex vector out. - * \ingroup fourier_analysis_blk - * - * The FFT operation is defined for a vector \f$x\f$ with \f$N\f$ uniformly - * sampled points by - * - * \f[ X(a) = \sum_{k=0}^{N-1} x(a) \cdot e^{-j 2\pi k a / N} \f] - * - * \f$ X = FFT\{x\} \f$ is the the FFT transform of \f$x(a)\f$, \f$j\f$ is - * the imaginary unit, \f$k\f$ and \f$a\f$ range from \f$0\f$ to \f$N-1\f$. - * - * The IFFT operation is defined for a vector \f$y\f$ with \f$N\f$ - * uniformly sampled points by - * - * \f[ Y(b) = \sum_{k=0}^{N-1} y(b) \cdot e^{j 2\pi k b / N} \f] - * - * \f$Y = IFFT\{y\}\f$ is the the inverse FFT transform of \f$y(b)\f$, - * \f$j\f$ is the imaginary unit, \f$k\f$ and \f$b\f$ range from \f$0\f$ to - * \f$N-1\f$. - * - * \b Note, that due to the underlying FFTW library, the output of a FFT - * followed by an IFFT (or the other way around) will be scaled i.e. - * \f$FFT\{ \, IFFT\{x\} \,\} = N \cdot x \neq x\f$. - * - * \see http://www.fftw.org/faq/section3.html#whyscaled - */ -class FFT_API fft_vfc : virtual public sync_block -{ -public: - // gr::fft::fft_vfc::sptr - typedef std::shared_ptr<fft_vfc> sptr; - - /*! \brief - * \param[in] fft_size N. - * \param[in] forward True performs FFT, False performs IFFT. - * \param[in] window Window function to be used. - * \param[in] nthreads Number of underlying threads. - */ - static sptr - make(int fft_size, bool forward, const std::vector<float>& window, int nthreads = 1); - - virtual void set_nthreads(int n) = 0; - - virtual int nthreads() const = 0; - - virtual bool set_window(const std::vector<float>& window) = 0; -}; - -} /* namespace fft */ -} /* namespace gr */ - -#endif /* INCLUDED_FFT_FFT_VFC_H */ diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt index e8ec301eab..48495f03f8 100644 --- a/gr-fft/lib/CMakeLists.txt +++ b/gr-fft/lib/CMakeLists.txt @@ -10,8 +10,7 @@ ######################################################################## add_library(gnuradio-fft fft.cc - fft_vcc_fftw.cc - fft_vfc_fftw.cc + fft_v_fftw.cc goertzel_fc_impl.cc goertzel.cc window.cc diff --git a/gr-fft/lib/ctrlport_probe_psd_impl.cc b/gr-fft/lib/ctrlport_probe_psd_impl.cc index 824d326cf5..8b0bfc5516 100644 --- a/gr-fft/lib/ctrlport_probe_psd_impl.cc +++ b/gr-fft/lib/ctrlport_probe_psd_impl.cc @@ -33,7 +33,7 @@ ctrlport_probe_psd_impl::ctrlport_probe_psd_impl(const std::string& id, d_id(id), d_desc(desc), d_len(len), - d_fft(len, true, 1) + d_fft(len, 1) { set_length(len); } diff --git a/gr-fft/lib/ctrlport_probe_psd_impl.h b/gr-fft/lib/ctrlport_probe_psd_impl.h index dc82acff4d..2f2d2c3455 100644 --- a/gr-fft/lib/ctrlport_probe_psd_impl.h +++ b/gr-fft/lib/ctrlport_probe_psd_impl.h @@ -30,7 +30,7 @@ private: boost::condition_variable condition_buffer_ready; std::vector<gr_complex> d_buffer; - gr::fft::fft_complex d_fft; + gr::fft::fft_complex_fwd d_fft; public: ctrlport_probe_psd_impl(const std::string& id, const std::string& desc, int len); diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc index dca635265b..9fc0a22f46 100644 --- a/gr-fft/lib/fft.cc +++ b/gr-fft/lib/fft.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2008,2011,2012 Free Software Foundation, Inc. + * Copyright 2003,2008,2011,2012,2020 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -141,7 +141,9 @@ static void export_wisdom() // ---------------------------------------------------------------- -fft_complex::fft_complex(int fft_size, bool forward, int nthreads) + +template <class T, bool forward> +fft<T, forward>::fft(int fft_size, int nthreads) : d_nthreads(nthreads), d_inbuf(fft_size), d_outbuf(fft_size) { gr::configure_default_loggers(d_logger, d_debug_logger, "fft_complex"); @@ -159,137 +161,57 @@ fft_complex::fft_complex(int fft_size, bool forward, int nthreads) lock_wisdom(); import_wisdom(); // load prior wisdom from disk - d_plan = fftwf_plan_dft_1d(fft_size, - reinterpret_cast<fftwf_complex*>(d_inbuf.data()), - reinterpret_cast<fftwf_complex*>(d_outbuf.data()), - forward ? FFTW_FORWARD : FFTW_BACKWARD, - FFTW_MEASURE); - + initialize_plan(fft_size); if (d_plan == NULL) { GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_1d failed"); + throw std::runtime_error("Creating fftw plan failed"); } export_wisdom(); // store new wisdom to disk unlock_wisdom(); } -fft_complex::~fft_complex() +template <> +void fft<gr_complex, true>::initialize_plan(int fft_size) { - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - fftwf_destroy_plan((fftwf_plan)d_plan); + d_plan = fftwf_plan_dft_1d(fft_size, + reinterpret_cast<fftwf_complex*>(d_inbuf.data()), + reinterpret_cast<fftwf_complex*>(d_outbuf.data()), + FFTW_FORWARD, + FFTW_MEASURE); } -void fft_complex::set_nthreads(int n) +template <> +void fft<gr_complex, false>::initialize_plan(int fft_size) { - if (n <= 0) { - throw std::out_of_range("gr::fft: invalid number of threads"); - } - d_nthreads = n; - -#ifdef FFTW3F_THREADS - fftwf_plan_with_nthreads(d_nthreads); -#endif + d_plan = fftwf_plan_dft_1d(fft_size, + reinterpret_cast<fftwf_complex*>(d_inbuf.data()), + reinterpret_cast<fftwf_complex*>(d_outbuf.data()), + FFTW_BACKWARD, + FFTW_MEASURE); } -void fft_complex::execute() { fftwf_execute((fftwf_plan)d_plan); } - -// ---------------------------------------------------------------- -fft_real_fwd::fft_real_fwd(int fft_size, int nthreads) - : d_nthreads(nthreads), d_inbuf(fft_size), d_outbuf(fft_size / 2 + 1) +template <> +void fft<float, true>::initialize_plan(int fft_size) { - gr::configure_default_loggers(d_logger, d_debug_logger, "fft_real_fwd"); - - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - static_assert(sizeof(fftwf_complex) == sizeof(gr_complex), - "The size of fftwf_complex is not equal to gr_complex"); - - if (fft_size <= 0) { - throw std::out_of_range("gr::fft: invalid fft_size"); - } - - config_threading(nthreads); - lock_wisdom(); - import_wisdom(); // load prior wisdom from disk - d_plan = fftwf_plan_dft_r2c_1d(fft_size, d_inbuf.data(), reinterpret_cast<fftwf_complex*>(d_outbuf.data()), FFTW_MEASURE); - - if (d_plan == NULL) { - GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_r2c_1d failed"); - } - export_wisdom(); // store new wisdom to disk - unlock_wisdom(); -} - -fft_real_fwd::~fft_real_fwd() -{ - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - fftwf_destroy_plan((fftwf_plan)d_plan); } -void fft_real_fwd::set_nthreads(int n) +template <> +void fft<float, false>::initialize_plan(int fft_size) { - if (n <= 0) { - throw std::out_of_range( - "gr::fft::fft_real_fwd::set_nthreads: invalid number of threads"); - } - d_nthreads = n; - -#ifdef FFTW3F_THREADS - fftwf_plan_with_nthreads(d_nthreads); -#endif -} - -void fft_real_fwd::execute() { fftwf_execute((fftwf_plan)d_plan); } - -// ---------------------------------------------------------------- - -fft_real_rev::fft_real_rev(int fft_size, int nthreads) - : d_nthreads(nthreads), d_inbuf(fft_size / 2 + 1), d_outbuf(fft_size) -{ - gr::configure_default_loggers(d_logger, d_debug_logger, "fft_real_rev"); - - // Hold global mutex during plan construction and destruction. - planner::scoped_lock lock(planner::mutex()); - - static_assert(sizeof(fftwf_complex) == sizeof(gr_complex), - "The size of fftwf_complex is not equal to gr_complex"); - - if (fft_size <= 0) { - throw std::out_of_range("gr::fft::fft_real_rev: invalid fft_size"); - } - - config_threading(nthreads); - lock_wisdom(); - import_wisdom(); // load prior wisdom from disk - - // FIXME If there's ever a chance that the planning functions - // will be called in multiple threads, we've got to ensure single - // threaded access. They are not thread-safe. d_plan = fftwf_plan_dft_c2r_1d(fft_size, reinterpret_cast<fftwf_complex*>(d_inbuf.data()), d_outbuf.data(), FFTW_MEASURE); - - if (d_plan == NULL) { - GR_LOG_ERROR(d_logger, "creating plan failed"); - throw std::runtime_error("fftwf_plan_dft_c2r_1d failed"); - } - export_wisdom(); // store new wisdom to disk - unlock_wisdom(); } -fft_real_rev::~fft_real_rev() + +template <class T, bool forward> +fft<T, forward>::~fft() { // Hold global mutex during plan construction and destruction. planner::scoped_lock lock(planner::mutex()); @@ -297,11 +219,11 @@ fft_real_rev::~fft_real_rev() fftwf_destroy_plan((fftwf_plan)d_plan); } -void fft_real_rev::set_nthreads(int n) +template <class T, bool forward> +void fft<T, forward>::set_nthreads(int n) { if (n <= 0) { - throw std::out_of_range( - "gr::fft::fft_real_rev::set_nthreads: invalid number of threads"); + throw std::out_of_range("gr::fft: invalid number of threads"); } d_nthreads = n; @@ -310,7 +232,16 @@ void fft_real_rev::set_nthreads(int n) #endif } -void fft_real_rev::execute() { fftwf_execute((fftwf_plan)d_plan); } +template <class T, bool forward> +void fft<T, forward>::execute() +{ + fftwf_execute((fftwf_plan)d_plan); +} + +template class fft<gr_complex, true>; +template class fft<gr_complex, false>; +template class fft<float, true>; +template class fft<float, false>; } /* namespace fft */ } /* namespace gr */ diff --git a/gr-fft/lib/fft_v_fftw.cc b/gr-fft/lib/fft_v_fftw.cc new file mode 100644 index 0000000000..387e63b458 --- /dev/null +++ b/gr-fft/lib/fft_v_fftw.cc @@ -0,0 +1,217 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2008,2010,2012,2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fft_v_fftw.h" +#include <math.h> +#include <string.h> +#include <volk/volk.h> + +namespace gr { +namespace fft { + +template <class T, bool forward> +typename fft_v<T, forward>::sptr fft_v<T, forward>::make(int fft_size, + const std::vector<float>& window, + bool shift, + int nthreads) +{ + return gnuradio::get_initial_sptr( + new fft_v_fftw<T, forward>(fft_size, window, shift, nthreads)); +} + +template <class T, bool forward> +fft_v_fftw<T, forward>::fft_v_fftw(int fft_size, + const std::vector<float>& window, + bool shift, + int nthreads) + : sync_block("fft_v_fftw", + io_signature::make(1, 1, fft_size * sizeof(T)), + io_signature::make(1, 1, fft_size * sizeof(gr_complex))), + d_fft_size(fft_size), + d_fft(fft_size, nthreads), + d_shift(shift) +{ + if (!set_window(window)) + throw std::runtime_error("fft_v: window not the same length as fft_size"); +} + +template <class T, bool forward> +void fft_v_fftw<T, forward>::set_nthreads(int n) +{ + d_fft.set_nthreads(n); +} + +template <class T, bool forward> +int fft_v_fftw<T, forward>::nthreads() const +{ + return d_fft.nthreads(); +} + +template <class T, bool forward> +bool fft_v_fftw<T, forward>::set_window(const std::vector<float>& window) +{ + if (window.empty() || window.size() == d_fft_size) { + d_window = window; + return true; + } else + return false; +} + +template <> +void fft_v_fftw<gr_complex, true>::fft_and_shift(const gr_complex* in, gr_complex* out) +{ + if (!d_window.empty()) { + gr_complex* dst = d_fft.get_inbuf(); + volk_32fc_32f_multiply_32fc(&dst[0], in, &d_window[0], d_fft_size); + } else { + memcpy(d_fft.get_inbuf(), in, sizeof(gr_complex) * d_fft_size); + } + d_fft.execute(); + if (d_shift) { + unsigned int len = (unsigned int)(ceil(d_fft_size / 2.0)); + memcpy( + &out[0], &d_fft.get_outbuf()[len], sizeof(gr_complex) * (d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft.get_outbuf()[0], sizeof(gr_complex) * len); + } else { + + memcpy(out, d_fft.get_outbuf(), sizeof(gr_complex) * d_fft_size); + } +} + +template <> +void fft_v_fftw<gr_complex, false>::fft_and_shift(const gr_complex* in, gr_complex* out) +{ + if (!d_window.empty()) { + gr_complex* dst = d_fft.get_inbuf(); + if (d_shift) { + unsigned int offset = d_fft_size / 2; + int fft_m_offset = d_fft_size - offset; + volk_32fc_32f_multiply_32fc(&dst[fft_m_offset], &in[0], &d_window[0], offset); + volk_32fc_32f_multiply_32fc( + &dst[0], &in[offset], &d_window[offset], d_fft_size - offset); + } else { + volk_32fc_32f_multiply_32fc(&dst[0], in, &d_window[0], d_fft_size); + } + } else { + if (d_shift) { // apply an ifft shift on the data + gr_complex* dst = d_fft.get_inbuf(); + unsigned int len = + (unsigned int)(floor(d_fft_size / 2.0)); // half length of complex array + memcpy(&dst[0], &in[len], sizeof(gr_complex) * (d_fft_size - len)); + memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex) * len); + } else { + memcpy(d_fft.get_inbuf(), in, sizeof(gr_complex) * d_fft_size); + } + } + d_fft.execute(); + memcpy(out, d_fft.get_outbuf(), sizeof(gr_complex) * d_fft_size); +} + +template <> +void fft_v_fftw<float, true>::fft_and_shift(const float* in, gr_complex* out) +{ + // copy input into optimally aligned buffer + if (!d_window.empty()) { + gr_complex* dst = d_fft.get_inbuf(); + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } else { + gr_complex* dst = d_fft.get_inbuf(); + for (unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion + dst[i] = in[i]; + } + + d_fft.execute(); + if (d_shift) { + unsigned int len = (unsigned int)(ceil(d_fft_size / 2.0)); + memcpy( + &out[0], &d_fft.get_outbuf()[len], sizeof(gr_complex) * (d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft.get_outbuf()[0], sizeof(gr_complex) * len); + } else { + + memcpy(out, d_fft.get_outbuf(), sizeof(gr_complex) * d_fft_size); + } +} + +template <> +void fft_v_fftw<float, false>::fft_and_shift(const float* in, gr_complex* out) +{ + // copy input into optimally aligned buffer + if (!d_window.empty()) { + gr_complex* dst = d_fft.get_inbuf(); + if (d_shift) { + unsigned int len = + (unsigned int)(floor(d_fft_size / 2.0)); // half length of complex array + for (unsigned int i = 0; i < len; i++) { + dst[i] = in[len + i] * d_window[len + i]; + } + for (unsigned int i = len; i < d_fft_size; i++) { + dst[i] = in[i - len] * d_window[i - len]; + } + } else { + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + + } else { + gr_complex* dst = d_fft.get_inbuf(); + if (d_shift) { + unsigned int len = + (unsigned int)(floor(d_fft_size / 2.0)); // half length of complex array + for (unsigned int i = 0; i < len; i++) { + dst[i] = in[len + i]; + } + for (unsigned int i = len; i < d_fft_size; i++) { + dst[i] = in[i - len]; + } + } else { + for (unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion + dst[i] = in[i]; + } + } + + // compute the fft + d_fft.execute(); + + // copy result to output stream + memcpy(out, d_fft.get_outbuf(), sizeof(gr_complex) * d_fft_size); +} + +template <class T, bool forward> +int fft_v_fftw<T, forward>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + auto in = reinterpret_cast<const T*>(input_items[0]); + auto out = reinterpret_cast<gr_complex*>(output_items[0]); + + int count = 0; + + while (count++ < noutput_items) { + + fft_and_shift(in, out); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; +} + +template class fft_v<gr_complex, true>; +template class fft_v<gr_complex, false>; +template class fft_v<float, true>; +template class fft_v<float, false>; +} /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/fft_vcc_fftw.h b/gr-fft/lib/fft_v_fftw.h index 54ed49337f..95f17c58c1 100644 --- a/gr-fft/lib/fft_vcc_fftw.h +++ b/gr-fft/lib/fft_v_fftw.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc. + * Copyright 2004,2007,2008,2012,2020 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -8,30 +8,32 @@ * */ -#ifndef INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H -#define INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H +#ifndef INCLUDED_FFT_FFT_V_FFTW_IMPL_H +#define INCLUDED_FFT_FFT_V_FFTW_IMPL_H #include <gnuradio/fft/fft.h> -#include <gnuradio/fft/fft_vcc.h> +#include <gnuradio/fft/fft_v.h> namespace gr { namespace fft { -class FFT_API fft_vcc_fftw : public fft_vcc +template <class T, bool forward> +class FFT_API fft_v_fftw : public fft_v<T, forward> { private: const unsigned int d_fft_size; - const bool d_forward; - fft_complex d_fft; + fft<gr_complex, forward> d_fft; std::vector<float> d_window; const bool d_shift; + void fft_and_shift(const T* in, gr_complex* out); public: - fft_vcc_fftw(int fft_size, - bool forward, - const std::vector<float>& window, - bool shift, - int nthreads = 1); + fft_v_fftw(int fft_size, + const std::vector<float>& window, + bool shift, + int nthreads = 1); + + ~fft_v_fftw() {} void set_nthreads(int n) override; int nthreads() const override; @@ -45,4 +47,4 @@ public: } /* namespace fft */ } /* namespace gr */ -#endif /* INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H */ +#endif /* INCLUDED_FFT_FFT_V_FFTW_IMPL_H */ diff --git a/gr-fft/lib/fft_vcc_fftw.cc b/gr-fft/lib/fft_vcc_fftw.cc deleted file mode 100644 index 076d7a63fd..0000000000 --- a/gr-fft/lib/fft_vcc_fftw.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007,2008,2010,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "fft_vcc_fftw.h" -#include <math.h> -#include <string.h> -#include <volk/volk.h> - -namespace gr { -namespace fft { - -fft_vcc::sptr fft_vcc::make(int fft_size, - bool forward, - const std::vector<float>& window, - bool shift, - int nthreads) -{ - return gnuradio::make_block_sptr<fft_vcc_fftw>( - fft_size, forward, window, shift, nthreads); -} - -fft_vcc_fftw::fft_vcc_fftw(int fft_size, - bool forward, - const std::vector<float>& window, - bool shift, - int nthreads) - : sync_block("fft_vcc_fftw", - io_signature::make(1, 1, fft_size * sizeof(gr_complex)), - io_signature::make(1, 1, fft_size * sizeof(gr_complex))), - d_fft_size(fft_size), - d_forward(forward), - d_fft(fft_size, forward, nthreads), - d_shift(shift) -{ - if (!set_window(window)) - throw std::runtime_error("fft_vcc: window not the same length as fft_size"); -} - -void fft_vcc_fftw::set_nthreads(int n) { d_fft.set_nthreads(n); } - -int fft_vcc_fftw::nthreads() const { return d_fft.nthreads(); } - -bool fft_vcc_fftw::set_window(const std::vector<float>& window) -{ - if (window.empty() || window.size() == d_fft_size) { - d_window = window; - return true; - } else - return false; -} - -int fft_vcc_fftw::work(int noutput_items, - gr_vector_const_void_star& input_items, - gr_vector_void_star& output_items) -{ - const gr_complex* in = (const gr_complex*)input_items[0]; - gr_complex* out = (gr_complex*)output_items[0]; - - unsigned int input_data_size = input_signature()->sizeof_stream_item(0); - unsigned int output_data_size = output_signature()->sizeof_stream_item(0); - - int count = 0; - - while (count++ < noutput_items) { - - // copy input into optimally aligned buffer - if (!d_window.empty()) { - gr_complex* dst = d_fft.get_inbuf(); - if (!d_forward && d_shift) { - unsigned int offset = d_fft_size / 2; - int fft_m_offset = d_fft_size - offset; - volk_32fc_32f_multiply_32fc( - &dst[fft_m_offset], &in[0], &d_window[0], offset); - volk_32fc_32f_multiply_32fc( - &dst[0], &in[offset], &d_window[offset], d_fft_size - offset); - } else { - volk_32fc_32f_multiply_32fc(&dst[0], in, &d_window[0], d_fft_size); - } - } else { - if (!d_forward && d_shift) { // apply an ifft shift on the data - gr_complex* dst = d_fft.get_inbuf(); - unsigned int len = (unsigned int)(floor( - d_fft_size / 2.0)); // half length of complex array - memcpy(&dst[0], &in[len], sizeof(gr_complex) * (d_fft_size - len)); - memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex) * len); - } else { - memcpy(d_fft.get_inbuf(), in, input_data_size); - } - } - - // compute the fft - d_fft.execute(); - - // copy result to our output - if (d_forward && d_shift) { // apply a fft shift on the data - unsigned int len = (unsigned int)(ceil(d_fft_size / 2.0)); - memcpy(&out[0], - &d_fft.get_outbuf()[len], - sizeof(gr_complex) * (d_fft_size - len)); - memcpy( - &out[d_fft_size - len], &d_fft.get_outbuf()[0], sizeof(gr_complex) * len); - } else { - memcpy(out, d_fft.get_outbuf(), output_data_size); - } - - in += d_fft_size; - out += d_fft_size; - } - - return noutput_items; -} - -} /* namespace fft */ -} /* namespace gr */ diff --git a/gr-fft/lib/fft_vfc_fftw.cc b/gr-fft/lib/fft_vfc_fftw.cc deleted file mode 100644 index 77d5d9caf2..0000000000 --- a/gr-fft/lib/fft_vfc_fftw.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007,2008,2010,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "fft_vfc_fftw.h" -#include <gnuradio/io_signature.h> -#include <math.h> -#include <string.h> - -namespace gr { -namespace fft { - -fft_vfc::sptr -fft_vfc::make(int fft_size, bool forward, const std::vector<float>& window, int nthreads) -{ - return gnuradio::make_block_sptr<fft_vfc_fftw>(fft_size, forward, window, nthreads); -} - -fft_vfc_fftw::fft_vfc_fftw(int fft_size, - bool forward, - const std::vector<float>& window, - int nthreads) - : sync_block("fft_vfc_fftw", - io_signature::make(1, 1, fft_size * sizeof(float)), - io_signature::make(1, 1, fft_size * sizeof(gr_complex))), - d_fft_size(fft_size), - d_fft(fft_size, forward, nthreads) -{ - if (!set_window(window)) - throw std::runtime_error("fft_vfc: window not the same length as fft_size"); -} - -void fft_vfc_fftw::set_nthreads(int n) { d_fft.set_nthreads(n); } - -int fft_vfc_fftw::nthreads() const { return d_fft.nthreads(); } - -bool fft_vfc_fftw::set_window(const std::vector<float>& window) -{ - if (window.empty() || window.size() == d_fft_size) { - d_window = window; - return true; - } else - return false; -} - -int fft_vfc_fftw::work(int noutput_items, - gr_vector_const_void_star& input_items, - gr_vector_void_star& output_items) -{ - const float* in = (const float*)input_items[0]; - gr_complex* out = (gr_complex*)output_items[0]; - - unsigned int output_data_size = output_signature()->sizeof_stream_item(0); - - int count = 0; - - while (count++ < noutput_items) { - - // copy input into optimally aligned buffer - if (!d_window.empty()) { - gr_complex* dst = d_fft.get_inbuf(); - for (unsigned int i = 0; i < d_fft_size; i++) // apply window - dst[i] = in[i] * d_window[i]; - } else { - gr_complex* dst = d_fft.get_inbuf(); - for (unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion - dst[i] = in[i]; - } - - // compute the fft - d_fft.execute(); - - // copy result to output stream - memcpy(out, d_fft.get_outbuf(), output_data_size); - - in += d_fft_size; - out += d_fft_size; - } - - return noutput_items; -} - -} /* namespace fft */ -} /* namespace gr */ diff --git a/gr-fft/lib/fft_vfc_fftw.h b/gr-fft/lib/fft_vfc_fftw.h deleted file mode 100644 index f641a80808..0000000000 --- a/gr-fft/lib/fft_vfc_fftw.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifndef INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H -#define INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H - -#include <gnuradio/fft/fft.h> -#include <gnuradio/fft/fft_vfc.h> - -namespace gr { -namespace fft { - -class FFT_API fft_vfc_fftw : public fft_vfc -{ -private: - const unsigned int d_fft_size; - fft_complex d_fft; - std::vector<float> d_window; - -public: - fft_vfc_fftw(int fft_size, - bool forward, - const std::vector<float>& window, - int nthreads = 1); - - void set_nthreads(int n) override; - int nthreads() const override; - bool set_window(const std::vector<float>& window) override; - - int work(int noutput_items, - gr_vector_const_void_star& input_items, - gr_vector_void_star& output_items) override; -}; - -} /* namespace fft */ -} /* namespace gr */ - -#endif /* INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H */ diff --git a/gr-fft/python/fft/CMakeLists.txt b/gr-fft/python/fft/CMakeLists.txt index e94f206352..2bd0afb0e1 100644 --- a/gr-fft/python/fft/CMakeLists.txt +++ b/gr-fft/python/fft/CMakeLists.txt @@ -10,6 +10,8 @@ include(GrPython) GR_PYTHON_INSTALL( FILES + fft_vcc.py + fft_vfc.py __init__.py logpwrfft.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft diff --git a/gr-fft/python/fft/__init__.py b/gr-fft/python/fft/__init__.py index d4d2c964cb..bb370a333a 100644 --- a/gr-fft/python/fft/__init__.py +++ b/gr-fft/python/fft/__init__.py @@ -20,3 +20,6 @@ except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "bindings")) from .fft_python import * + +from .fft_vcc import fft_vcc +from .fft_vfc import fft_vfc
\ No newline at end of file diff --git a/gr-fft/python/fft/bindings/CMakeLists.txt b/gr-fft/python/fft/bindings/CMakeLists.txt index 4ca22cf43e..f67e6a81e0 100644 --- a/gr-fft/python/fft/bindings/CMakeLists.txt +++ b/gr-fft/python/fft/bindings/CMakeLists.txt @@ -6,10 +6,8 @@ include(GrPybind) list(APPEND fft_python_files #ctrlport_probe_psd_python.cc - fft_python.cc fft_shift_python.cc - fft_vcc_python.cc - fft_vfc_python.cc + fft_v_python.cc goertzel_python.cc goertzel_fc_python.cc window_python.cc diff --git a/gr-fft/python/fft/bindings/docstrings/fft_pydoc_template.h b/gr-fft/python/fft/bindings/docstrings/fft_pydoc_template.h deleted file mode 100644 index 0f37f06b93..0000000000 --- a/gr-fft/python/fft/bindings/docstrings/fft_pydoc_template.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2020 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#include "pydoc_macros.h" -#define D(...) DOC(gr, fft, __VA_ARGS__) -/* - This file contains placeholders for docstrings for the Python bindings. - Do not edit! These were automatically extracted during the binding process - and will be overwritten during the build process - */ - - -static const char* __doc_gr_fft_planner = R"doc()doc"; - - -static const char* __doc_gr_fft_planner_planner_0 = R"doc()doc"; - - -static const char* __doc_gr_fft_planner_planner_1 = R"doc()doc"; - - -static const char* __doc_gr_fft_planner_mutex = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_fft_complex = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_get_inbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_get_outbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_inbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_outbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_set_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_complex_execute = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_fft_real_fwd = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_get_inbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_get_outbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_inbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_outbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_set_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_fwd_execute = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_fft_real_rev = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_get_inbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_get_outbuf = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_inbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_outbuf_length = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_set_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_real_rev_execute = R"doc()doc"; diff --git a/gr-fft/python/fft/bindings/docstrings/fft_v_pydoc_template.h b/gr-fft/python/fft/bindings/docstrings/fft_v_pydoc_template.h new file mode 100644 index 0000000000..4a1b3ede3e --- /dev/null +++ b/gr-fft/python/fft/bindings/docstrings/fft_v_pydoc_template.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#include "pydoc_macros.h" +#define D(...) DOC(gr, fft, __VA_ARGS__) +/* + This file contains placeholders for docstrings for the Python bindings. + Do not edit! These were automatically extracted during the binding process + and will be overwritten during the build process + */ diff --git a/gr-fft/python/fft/bindings/docstrings/fft_vcc_pydoc_template.h b/gr-fft/python/fft/bindings/docstrings/fft_vcc_pydoc_template.h deleted file mode 100644 index ecf12fc7f5..0000000000 --- a/gr-fft/python/fft/bindings/docstrings/fft_vcc_pydoc_template.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#include "pydoc_macros.h" -#define D(...) DOC(gr, fft, __VA_ARGS__) -/* - This file contains placeholders for docstrings for the Python bindings. - Do not edit! These were automatically extracted during the binding process - and will be overwritten during the build process - */ - - -static const char* __doc_gr_fft_fft_vcc = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_fft_vcc_0 = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_fft_vcc_1 = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_make = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_set_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vcc_set_window = R"doc()doc"; diff --git a/gr-fft/python/fft/bindings/docstrings/fft_vfc_pydoc_template.h b/gr-fft/python/fft/bindings/docstrings/fft_vfc_pydoc_template.h deleted file mode 100644 index 6c8a4b15b7..0000000000 --- a/gr-fft/python/fft/bindings/docstrings/fft_vfc_pydoc_template.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#include "pydoc_macros.h" -#define D(...) DOC(gr, fft, __VA_ARGS__) -/* - This file contains placeholders for docstrings for the Python bindings. - Do not edit! These were automatically extracted during the binding process - and will be overwritten during the build process - */ - - -static const char* __doc_gr_fft_fft_vfc = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_fft_vfc_0 = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_fft_vfc_1 = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_make = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_set_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_nthreads = R"doc()doc"; - - -static const char* __doc_gr_fft_fft_vfc_set_window = R"doc()doc"; diff --git a/gr-fft/python/fft/bindings/fft_python.cc b/gr-fft/python/fft/bindings/fft_python.cc deleted file mode 100644 index 268edfaa24..0000000000 --- a/gr-fft/python/fft/bindings/fft_python.cc +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2020 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -/***********************************************************************************/ -/* This file is automatically generated using bindtool and can be manually edited */ -/* The following lines can be configured to regenerate this file during cmake */ -/* If manual edits are made, the following tags should be modified accordingly. */ -/* BINDTOOL_GEN_AUTOMATIC(0) */ -/* BINDTOOL_USE_PYGCCXML(0) */ -/* BINDTOOL_HEADER_FILE(fft.h) */ -/* BINDTOOL_HEADER_FILE_HASH(ebbb274b1b433908749981712d96b3e9) */ -/***********************************************************************************/ - -#include <pybind11/complex.h> -#include <pybind11/pybind11.h> -#include <pybind11/stl.h> - -namespace py = pybind11; - -#include <gnuradio/fft/fft.h> -// pydoc.h is automatically generated in the build directory -#include <fft_pydoc.h> - -void bind_fft(py::module& m) -{ - - using planner = ::gr::fft::planner; - using fft_complex = ::gr::fft::fft_complex; - using fft_real_fwd = ::gr::fft::fft_real_fwd; - using fft_real_rev = ::gr::fft::fft_real_rev; - - - py::class_<planner, std::shared_ptr<planner>>(m, "planner", D(planner)) - - .def(py::init<>(), D(planner, planner, 0)) - .def(py::init<gr::fft::planner const&>(), py::arg("arg0"), D(planner, planner, 1)) - - - .def_static("mutex", &planner::mutex, D(planner, mutex)) - - ; - - - py::class_<fft_complex, std::shared_ptr<fft_complex>>( - m, "fft_complex", D(fft_complex)) - - .def(py::init<int, bool, int>(), - py::arg("fft_size"), - py::arg("forward") = true, - py::arg("nthreads") = 1, - D(fft_complex, fft_complex)) - - - .def("get_inbuf", &fft_complex::get_inbuf, D(fft_complex, get_inbuf)) - - - .def("get_outbuf", &fft_complex::get_outbuf, D(fft_complex, get_outbuf)) - - - .def("inbuf_length", &fft_complex::inbuf_length, D(fft_complex, inbuf_length)) - - - .def("outbuf_length", &fft_complex::outbuf_length, D(fft_complex, outbuf_length)) - - - .def("set_nthreads", - &fft_complex::set_nthreads, - py::arg("n"), - D(fft_complex, set_nthreads)) - - - .def("nthreads", &fft_complex::nthreads, D(fft_complex, nthreads)) - - - .def("execute", &fft_complex::execute, D(fft_complex, execute)) - - ; - - - py::class_<fft_real_fwd, std::shared_ptr<fft_real_fwd>>( - m, "fft_real_fwd", D(fft_real_fwd)) - - .def(py::init<int, int>(), - py::arg("fft_size"), - py::arg("nthreads") = 1, - D(fft_real_fwd, fft_real_fwd)) - - - .def("get_inbuf", &fft_real_fwd::get_inbuf, D(fft_real_fwd, get_inbuf)) - - - .def("get_outbuf", &fft_real_fwd::get_outbuf, D(fft_real_fwd, get_outbuf)) - - - .def("inbuf_length", &fft_real_fwd::inbuf_length, D(fft_real_fwd, inbuf_length)) - - - .def( - "outbuf_length", &fft_real_fwd::outbuf_length, D(fft_real_fwd, outbuf_length)) - - - .def("set_nthreads", - &fft_real_fwd::set_nthreads, - py::arg("n"), - D(fft_real_fwd, set_nthreads)) - - - .def("nthreads", &fft_real_fwd::nthreads, D(fft_real_fwd, nthreads)) - - - .def("execute", &fft_real_fwd::execute, D(fft_real_fwd, execute)) - - ; - - - py::class_<fft_real_rev, std::shared_ptr<fft_real_rev>>( - m, "fft_real_rev", D(fft_real_rev)) - - .def(py::init<int, int>(), - py::arg("fft_size"), - py::arg("nthreads") = 1, - D(fft_real_rev, fft_real_rev)) - - - .def("get_inbuf", &fft_real_rev::get_inbuf, D(fft_real_rev, get_inbuf)) - - - .def("get_outbuf", &fft_real_rev::get_outbuf, D(fft_real_rev, get_outbuf)) - - - .def("inbuf_length", &fft_real_rev::inbuf_length, D(fft_real_rev, inbuf_length)) - - - .def( - "outbuf_length", &fft_real_rev::outbuf_length, D(fft_real_rev, outbuf_length)) - - - .def("set_nthreads", - &fft_real_rev::set_nthreads, - py::arg("n"), - D(fft_real_rev, set_nthreads)) - - - .def("nthreads", &fft_real_rev::nthreads, D(fft_real_rev, nthreads)) - - - .def("execute", &fft_real_rev::execute, D(fft_real_rev, execute)) - - ; -} diff --git a/gr-fft/python/fft/bindings/fft_vcc_python.cc b/gr-fft/python/fft/bindings/fft_v_python.cc index 66c21c2db1..720c484863 100644 --- a/gr-fft/python/fft/bindings/fft_vcc_python.cc +++ b/gr-fft/python/fft/bindings/fft_v_python.cc @@ -13,8 +13,8 @@ /* If manual edits are made, the following tags should be modified accordingly. */ /* BINDTOOL_GEN_AUTOMATIC(0) */ /* BINDTOOL_USE_PYGCCXML(0) */ -/* BINDTOOL_HEADER_FILE(fft_vcc.h) */ -/* BINDTOOL_HEADER_FILE_HASH(815bbb036e65e51800b2732772a9eaeb) */ +/* BINDTOOL_HEADER_FILE(fft_v.h) */ +/* BINDTOOL_HEADER_FILE_HASH(ef3398e963b1b296e309b81721bef8cb) */ /***********************************************************************************/ #include <pybind11/complex.h> @@ -23,42 +23,35 @@ namespace py = pybind11; -#include <gnuradio/fft/fft_vcc.h> +#include <gnuradio/fft/fft_v.h> // pydoc.h is automatically generated in the build directory -#include <fft_vcc_pydoc.h> +#include <fft_v_pydoc.h> -void bind_fft_vcc(py::module& m) -{ - - using fft_vcc = ::gr::fft::fft_vcc; +template <class T, bool forward> +void bind_fft_v_template(py::module& m, const char* classname) +{ + using fft_v_blk = gr::fft::fft_v<T, forward>; - py::class_<fft_vcc, + py::class_<fft_v_blk, gr::sync_block, gr::block, gr::basic_block, - std::shared_ptr<fft_vcc>>(m, "fft_vcc", D(fft_vcc)) - - .def(py::init(&fft_vcc::make), + std::shared_ptr<fft_v_blk>>(m, classname) + .def(py::init(&gr::fft::fft_v<T, forward>::make), py::arg("fft_size"), - py::arg("forward"), py::arg("window"), py::arg("shift") = false, - py::arg("nthreads") = 1, - D(fft_vcc, make)) - - - .def("set_nthreads", - &fft_vcc::set_nthreads, - py::arg("n"), - D(fft_vcc, set_nthreads)) - - - .def("nthreads", &fft_vcc::nthreads, D(fft_vcc, nthreads)) - + py::arg("nthreads") = 1) + .def("set_nthreads", &fft_v_blk::set_nthreads, py::arg("n")) + .def("nthreads", &fft_v_blk::nthreads) + .def("set_window", &fft_v_blk::set_window, py::arg("window")); +} - .def("set_window", - &fft_vcc::set_window, - py::arg("window"), - D(fft_vcc, set_window)); +void bind_fft_v(py::module& m) +{ + bind_fft_v_template<gr_complex, true>(m, "fft_vcc_fwd"); + bind_fft_v_template<gr_complex, false>(m, "fft_vcc_rev"); + bind_fft_v_template<float, true>(m, "fft_vfc_fwd"); + bind_fft_v_template<float, false>(m, "fft_vfc_rev"); } diff --git a/gr-fft/python/fft/bindings/fft_vfc_python.cc b/gr-fft/python/fft/bindings/fft_vfc_python.cc deleted file mode 100644 index d8faefec65..0000000000 --- a/gr-fft/python/fft/bindings/fft_vfc_python.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -/***********************************************************************************/ -/* This file is automatically generated using bindtool and can be manually edited */ -/* The following lines can be configured to regenerate this file during cmake */ -/* If manual edits are made, the following tags should be modified accordingly. */ -/* BINDTOOL_GEN_AUTOMATIC(0) */ -/* BINDTOOL_USE_PYGCCXML(0) */ -/* BINDTOOL_HEADER_FILE(fft_vfc.h) */ -/* BINDTOOL_HEADER_FILE_HASH(4de2f3aa3119e3d636a1a533974a2e95) */ -/***********************************************************************************/ - -#include <pybind11/complex.h> -#include <pybind11/pybind11.h> -#include <pybind11/stl.h> - -namespace py = pybind11; - -#include <gnuradio/fft/fft_vfc.h> -// pydoc.h is automatically generated in the build directory -#include <fft_vfc_pydoc.h> - -void bind_fft_vfc(py::module& m) -{ - using fft_vfc = gr::fft::fft_vfc; - - - py::class_<fft_vfc, - gr::sync_block, - gr::block, - gr::basic_block, - std::shared_ptr<fft_vfc>>(m, "fft_vfc", D(fft_vfc)) - - .def(py::init(&fft_vfc::make), - py::arg("fft_size"), - py::arg("forward"), - py::arg("window"), - py::arg("nthreads") = 1, - D(fft_vfc, make)) - - - .def("set_nthreads", - &fft_vfc::set_nthreads, - py::arg("n"), - D(fft_vfc, set_nthreads)) - - - .def("nthreads", &fft_vfc::nthreads, D(fft_vfc, nthreads)) - - - .def("set_window", - &fft_vfc::set_window, - py::arg("window"), - D(fft_vfc, set_window)); -} diff --git a/gr-fft/python/fft/bindings/python_bindings.cc b/gr-fft/python/fft/bindings/python_bindings.cc index a1c191ed3d..ea94cd7b8e 100644 --- a/gr-fft/python/fft/bindings/python_bindings.cc +++ b/gr-fft/python/fft/bindings/python_bindings.cc @@ -16,10 +16,8 @@ namespace py = pybind11; // void bind_ctrlport_probe_psd(py::module&); -void bind_fft(py::module&); void bind_fft_shift(py::module&); -void bind_fft_vcc(py::module&); -void bind_fft_vfc(py::module&); +void bind_fft_v(py::module&); void bind_goertzel(py::module&); void bind_goertzel_fc(py::module&); void bind_window(py::module&); @@ -44,10 +42,8 @@ PYBIND11_MODULE(fft_python, m) py::module::import("gnuradio.gr"); // bind_ctrlport_probe_psd(m); - bind_fft(m); bind_fft_shift(m); - bind_fft_vcc(m); - bind_fft_vfc(m); + bind_fft_v(m); bind_goertzel(m); bind_goertzel_fc(m); bind_window(m); diff --git a/gr-fft/python/fft/fft_vcc.py b/gr-fft/python/fft/fft_vcc.py new file mode 100644 index 0000000000..3f5dae91b0 --- /dev/null +++ b/gr-fft/python/fft/fft_vcc.py @@ -0,0 +1,22 @@ +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from . import fft_python as fft + + +class fft_vcc(): + def __new__(self, fft_size, + forward, + window, + shift=False, + nthreads=1): + if forward: + return fft.fft_vcc_fwd(fft_size, window, shift, nthreads) + else: + return fft.fft_vcc_rev(fft_size, window, shift, nthreads) diff --git a/gr-fft/python/fft/fft_vfc.py b/gr-fft/python/fft/fft_vfc.py new file mode 100644 index 0000000000..5194b72f29 --- /dev/null +++ b/gr-fft/python/fft/fft_vfc.py @@ -0,0 +1,22 @@ +# +# Copyright 2020 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# + +from . import fft_python as fft + + +class fft_vfc(): + def __new__(self, fft_size, + forward, + window, + shift=False, + nthreads=1): + if forward: + return fft.fft_vfc_fwd(fft_size, window, shift, nthreads) + else: + return fft.fft_vfc_rev(fft_size, window, shift, nthreads) diff --git a/gr-filter/include/gnuradio/filter/fft_filter.h b/gr-filter/include/gnuradio/filter/fft_filter.h index 82cb0ecbd5..8bb7f56c93 100644 --- a/gr-filter/include/gnuradio/filter/fft_filter.h +++ b/gr-filter/include/gnuradio/filter/fft_filter.h @@ -165,9 +165,9 @@ private: int d_nsamples; int d_fftsize; // fftsize = ntaps + nsamples - 1 const int d_decimation; - std::unique_ptr<fft::fft_complex> d_fwdfft; // forward "plan" - std::unique_ptr<fft::fft_complex> d_invfft; // inverse "plan" - int d_nthreads; // number of FFTW threads to use + std::unique_ptr<fft::fft_complex_fwd> d_fwdfft; // forward "plan" + std::unique_ptr<fft::fft_complex_rev> d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add std::vector<gr_complex> d_taps; // stores time domain taps volk::vector<gr_complex> d_xformed_taps; // Fourier xformed taps @@ -269,9 +269,9 @@ private: int d_nsamples; int d_fftsize; // fftsize = ntaps + nsamples - 1 const int d_decimation; - std::unique_ptr<fft::fft_complex> d_fwdfft; // forward "plan" - std::unique_ptr<fft::fft_complex> d_invfft; // inverse "plan" - int d_nthreads; // number of FFTW threads to use + std::unique_ptr<fft::fft_complex_fwd> d_fwdfft; // forward "plan" + std::unique_ptr<fft::fft_complex_rev> d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add std::vector<float> d_taps; // stores time domain taps volk::vector<gr_complex> d_xformed_taps; // Fourier xformed taps diff --git a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h index 81131f9eb4..8f41065068 100644 --- a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h +++ b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h @@ -94,7 +94,7 @@ protected: std::vector<kernel::fft_filter_ccf> d_fft_filters; std::vector<std::vector<float>> d_taps; unsigned int d_taps_per_filter; - fft::fft_complex d_fft; + fft::fft_complex_rev* d_fft; public: /*! @@ -103,7 +103,6 @@ public: * channels <EM>M</EM> * \param taps (vector/list of floats) The prototype filter to * populate the filterbank. - * \param fft_forward (bool) use a forward or inverse FFT (default=false). */ polyphase_filterbank(unsigned int nfilts, const std::vector<float>& taps, diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc index 1cfc8b4796..a9a7bd73e3 100644 --- a/gr-filter/lib/fft_filter.cc +++ b/gr-filter/lib/fft_filter.cc @@ -217,8 +217,8 @@ void fft_filter_ccc::compute_sizes(int ntaps) // compute new plans if (d_fftsize != old_fftsize) { - d_fwdfft = boost::make_unique<fft::fft_complex>(d_fftsize, true, d_nthreads); - d_invfft = boost::make_unique<fft::fft_complex>(d_fftsize, false, d_nthreads); + d_fwdfft = boost::make_unique<fft::fft_complex_fwd>(d_fftsize, d_nthreads); + d_invfft = boost::make_unique<fft::fft_complex_rev>(d_fftsize, d_nthreads); d_xformed_taps.resize(d_fftsize); } } @@ -349,8 +349,8 @@ void fft_filter_ccf::compute_sizes(int ntaps) // compute new plans if (d_fftsize != old_fftsize) { - d_fwdfft = boost::make_unique<fft::fft_complex>(d_fftsize, true, d_nthreads); - d_invfft = boost::make_unique<fft::fft_complex>(d_fftsize, false, d_nthreads); + d_fwdfft = boost::make_unique<fft::fft_complex_fwd>(d_fftsize, d_nthreads); + d_invfft = boost::make_unique<fft::fft_complex_rev>(d_fftsize, d_nthreads); d_xformed_taps.resize(d_fftsize); } } diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.cc b/gr-filter/lib/pfb_channelizer_ccf_impl.cc index 7aa9493323..106d5ffe55 100644 --- a/gr-filter/lib/pfb_channelizer_ccf_impl.cc +++ b/gr-filter/lib/pfb_channelizer_ccf_impl.cc @@ -37,7 +37,7 @@ pfb_channelizer_ccf_impl::pfb_channelizer_ccf_impl(unsigned int nfilts, : block("pfb_channelizer_ccf", io_signature::make(nfilts, nfilts, sizeof(gr_complex)), io_signature::make(1, nfilts, sizeof(gr_complex))), - polyphase_filterbank(nfilts, taps, false), + polyphase_filterbank(nfilts, taps), d_updated(false), d_oversample_rate(oversample_rate) { @@ -162,7 +162,7 @@ int pfb_channelizer_ccf_impl::general_work(int noutput_items, last = i; while (i >= 0) { in = (gr_complex*)input_items[j]; - d_fft.get_inbuf()[d_idxlut[j]] = d_fir_filters[i].filter(&in[n]); + d_fft->get_inbuf()[d_idxlut[j]] = d_fir_filters[i].filter(&in[n]); j++; i--; } @@ -170,7 +170,7 @@ int pfb_channelizer_ccf_impl::general_work(int noutput_items, i = d_nfilts - 1; while (i > last) { in = (gr_complex*)input_items[j]; - d_fft.get_inbuf()[d_idxlut[j]] = d_fir_filters[i].filter(&in[n - 1]); + d_fft->get_inbuf()[d_idxlut[j]] = d_fir_filters[i].filter(&in[n - 1]); j++; i--; } @@ -178,12 +178,12 @@ int pfb_channelizer_ccf_impl::general_work(int noutput_items, n += (i + d_rate_ratio) >= (int)d_nfilts; // despin through FFT - d_fft.execute(); + d_fft->execute(); // Send to output channels for (unsigned int nn = 0; nn < noutputs; nn++) { out = (gr_complex*)output_items[nn]; - out[oo] = d_fft.get_outbuf()[d_channel_map[nn]]; + out[oo] = d_fft->get_outbuf()[d_channel_map[nn]]; } oo++; } diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc index 5a86efb62a..ef561e5895 100644 --- a/gr-filter/lib/pfb_decimator_ccf_impl.cc +++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc @@ -157,14 +157,14 @@ int pfb_decimator_ccf_impl::work_fir_fft(int noutput_items, for (unsigned int j = 0; j < d_rate; j++) { // Take in the items from the first input stream to d_rate in = (gr_complex*)input_items[d_rate - 1 - j]; - d_fft.get_inbuf()[j] = d_fir_filters[j].filter(&in[i]); + d_fft->get_inbuf()[j] = d_fir_filters[j].filter(&in[i]); } // Perform the FFT to do the complex multiply despinning for all channels - d_fft.execute(); + d_fft->execute(); // Select only the desired channel out - out[i] = d_fft.get_outbuf()[d_chan]; + out[i] = d_fft->get_outbuf()[d_chan]; } return noutput_items; @@ -218,14 +218,14 @@ int pfb_decimator_ccf_impl::work_fft_fft(int noutput_items, // an FFT. for (i = 0; i < noutput_items; i++) { for (unsigned int j = 0; j < d_rate; j++) { - d_fft.get_inbuf()[j] = d_tmp[j * noutput_items + i]; + d_fft->get_inbuf()[j] = d_tmp[j * noutput_items + i]; } // Perform the FFT to do the complex multiply despinning for all channels - d_fft.execute(); + d_fft->execute(); // Select only the desired channel out - out[i] = d_fft.get_outbuf()[d_chan]; + out[i] = d_fft->get_outbuf()[d_chan]; } return noutput_items; diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc index d33ee84e6e..f4c97d0e2d 100644 --- a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc +++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc @@ -37,8 +37,7 @@ pfb_synthesizer_ccf_impl::pfb_synthesizer_ccf_impl(unsigned int numchans, d_updated(false), d_numchans(numchans), d_state(0), - d_twox(twox ? 2 : 1), - d_fft(d_twox * d_numchans, false) + d_twox(twox ? 2 : 1) { // set up 2x multiplier; if twox==True, set to 2, otherwise to 1 if (d_numchans % d_twox != 0) { @@ -61,7 +60,8 @@ pfb_synthesizer_ccf_impl::pfb_synthesizer_ccf_impl(unsigned int numchans, set_taps(taps); // Create the IFFT to handle the input channel rotations - std::fill_n(d_fft.get_inbuf(), d_twox * d_numchans, 0); + d_fft = new fft::fft_complex_rev(d_twox * d_numchans); + std::fill_n(d_fft->get_inbuf(), d_twox * d_numchans, 0); set_output_multiple(d_numchans); } @@ -206,7 +206,7 @@ void pfb_synthesizer_ccf_impl::set_channel_map(const std::vector<int>& map) d_channel_map = map; // Zero out fft buffer so that unused channels are always 0 - std::fill_n(d_fft.get_inbuf(), d_twox * d_numchans, 0); + std::fill_n(d_fft->get_inbuf(), d_twox * d_numchans, 0); } } @@ -234,14 +234,14 @@ int pfb_synthesizer_ccf_impl::work(int noutput_items, for (n = 0; n < noutput_items / d_numchans; n++) { for (i = 0; i < ninputs; i++) { in = (gr_complex*)input_items[i]; - d_fft.get_inbuf()[d_channel_map[i]] = in[n]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; } // spin through IFFT - d_fft.execute(); + d_fft->execute(); for (i = 0; i < d_numchans; i++) { - out[i] = d_filters[i].filter(d_fft.get_outbuf()[i]); + out[i] = d_filters[i].filter(d_fft->get_outbuf()[i]); } out += d_numchans; } @@ -253,20 +253,20 @@ int pfb_synthesizer_ccf_impl::work(int noutput_items, for (i = 0; i < ninputs; i++) { // in = (gr_complex*)input_items[ninputs-i-1]; in = (gr_complex*)input_items[i]; - d_fft.get_inbuf()[d_channel_map[i]] = in[n]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; } // spin through IFFT - d_fft.execute(); + d_fft->execute(); // Output is sum of two filters, but the input buffer to the filters must be // circularly shifted by numchans every time through, done by using d_state to // determine which IFFT buffer position to pull from. for (i = 0; i < d_numchans; i++) { out[i] = - d_filters[i].filter(d_fft.get_outbuf()[d_state * d_numchans + i]); + d_filters[i].filter(d_fft->get_outbuf()[d_state * d_numchans + i]); out[i] += d_filters[d_numchans + i].filter( - d_fft.get_outbuf()[(d_state ^ 1) * d_numchans + i]); + d_fft->get_outbuf()[(d_state ^ 1) * d_numchans + i]); } d_state ^= 1; diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.h b/gr-filter/lib/pfb_synthesizer_ccf_impl.h index 59b573526a..f2375cb19b 100644 --- a/gr-filter/lib/pfb_synthesizer_ccf_impl.h +++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.h @@ -30,12 +30,12 @@ private: bool d_updated; unsigned int d_numchans; unsigned int d_taps_per_filter; + fft::fft_complex_rev* d_fft; std::vector<kernel::fir_filter_with_buffer_ccf> d_filters; std::vector<std::vector<float>> d_taps; int d_state; std::vector<int> d_channel_map; unsigned int d_twox; - fft::fft_complex d_fft; gr::thread::mutex d_mutex; // mutex to protect set/work access /*! diff --git a/gr-filter/lib/polyphase_filterbank.cc b/gr-filter/lib/polyphase_filterbank.cc index a44309e70b..f6d2e70daa 100644 --- a/gr-filter/lib/polyphase_filterbank.cc +++ b/gr-filter/lib/polyphase_filterbank.cc @@ -18,11 +18,10 @@ namespace gr { namespace filter { namespace kernel { - polyphase_filterbank::polyphase_filterbank(unsigned int nfilts, const std::vector<float>& taps, bool fft_forward) - : d_nfilts(nfilts), d_fft(nfilts, fft_forward) + : d_nfilts(nfilts) { d_fir_filters.reserve(d_nfilts); d_fft_filters.reserve(d_nfilts); @@ -36,6 +35,9 @@ polyphase_filterbank::polyphase_filterbank(unsigned int nfilts, // Now, actually set the filters' taps set_taps(taps); + + // Create the FFT to handle the output de-spinning of the channels + d_fft = new fft::fft_complex_rev(d_nfilts); } polyphase_filterbank::~polyphase_filterbank() {} diff --git a/gr-filter/python/filter/bindings/fft_filter_python.cc b/gr-filter/python/filter/bindings/fft_filter_python.cc index 7c9a0169e2..44e8a1c81b 100644 --- a/gr-filter/python/filter/bindings/fft_filter_python.cc +++ b/gr-filter/python/filter/bindings/fft_filter_python.cc @@ -14,7 +14,7 @@ /* BINDTOOL_GEN_AUTOMATIC(0) */ /* BINDTOOL_USE_PYGCCXML(0) */ /* BINDTOOL_HEADER_FILE(fft_filter.h) */ -/* BINDTOOL_HEADER_FILE_HASH(c695667a132764030a1dcb5daa4df053) */ +/* BINDTOOL_HEADER_FILE_HASH(ba4bcb2a6271a7c9db0b1fc2c39f00ee) */ /***********************************************************************************/ #include <pybind11/complex.h> diff --git a/gr-filter/python/filter/bindings/polyphase_filterbank_python.cc b/gr-filter/python/filter/bindings/polyphase_filterbank_python.cc index c0872fe60b..d1eaa68643 100644 --- a/gr-filter/python/filter/bindings/polyphase_filterbank_python.cc +++ b/gr-filter/python/filter/bindings/polyphase_filterbank_python.cc @@ -14,7 +14,7 @@ /* BINDTOOL_GEN_AUTOMATIC(0) */ /* BINDTOOL_USE_PYGCCXML(0) */ /* BINDTOOL_HEADER_FILE(polyphase_filterbank.h) */ -/* BINDTOOL_HEADER_FILE_HASH(8651c06a82eb420afdb769759d3fa4bd) */ +/* BINDTOOL_HEADER_FILE_HASH(8dc0395542b870d22b4d596530e6fc7d) */ /***********************************************************************************/ #include <pybind11/complex.h> diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc index 8ba0c67bc3..e4578eae15 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.cc +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -92,7 +92,7 @@ freq_sink_c_impl::freq_sink_c_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize * sizeof(float)); @@ -458,7 +458,7 @@ bool freq_sink_c_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); volk_free(d_fbuf); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h index 975b42e8ec..66fce9d946 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.h +++ b/gr-qtgui/lib/freq_sink_c_impl.h @@ -42,7 +42,7 @@ private: const pmt::pmt_t d_port_bw; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; std::vector<gr_complex*> d_residbufs; diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc index 3bc5f705e4..5fc70157af 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.cc +++ b/gr-qtgui/lib/freq_sink_f_impl.cc @@ -92,7 +92,7 @@ freq_sink_f_impl::freq_sink_f_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize, true); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize * sizeof(float)); @@ -461,7 +461,7 @@ bool freq_sink_f_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); volk_free(d_fbuf); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h index a5c3f7615f..67fe4094af 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.h +++ b/gr-qtgui/lib/freq_sink_f_impl.h @@ -42,7 +42,7 @@ private: const pmt::pmt_t d_port_bw; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; std::vector<float*> d_residbufs; diff --git a/gr-qtgui/lib/sink_c_impl.cc b/gr-qtgui/lib/sink_c_impl.cc index 39bd74aa3e..5277da256d 100644 --- a/gr-qtgui/lib/sink_c_impl.cc +++ b/gr-qtgui/lib/sink_c_impl.cc @@ -92,7 +92,7 @@ sink_c_impl::sink_c_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_index = 0; d_residbuf = @@ -279,7 +279,7 @@ void sink_c_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); } } diff --git a/gr-qtgui/lib/sink_c_impl.h b/gr-qtgui/lib/sink_c_impl.h index 466fcfd384..105fe54ab0 100644 --- a/gr-qtgui/lib/sink_c_impl.h +++ b/gr-qtgui/lib/sink_c_impl.h @@ -40,7 +40,7 @@ private: const pmt::pmt_t d_port; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; gr_complex* d_residbuf; diff --git a/gr-qtgui/lib/sink_f_impl.cc b/gr-qtgui/lib/sink_f_impl.cc index acaf4b4e09..9b10876da9 100644 --- a/gr-qtgui/lib/sink_f_impl.cc +++ b/gr-qtgui/lib/sink_f_impl.cc @@ -91,7 +91,7 @@ sink_f_impl::sink_f_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_index = 0; d_residbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); @@ -273,7 +273,7 @@ void sink_f_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); } } diff --git a/gr-qtgui/lib/sink_f_impl.h b/gr-qtgui/lib/sink_f_impl.h index fb954b6875..56731240df 100644 --- a/gr-qtgui/lib/sink_f_impl.h +++ b/gr-qtgui/lib/sink_f_impl.h @@ -38,7 +38,7 @@ private: const pmt::pmt_t d_port; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; float* d_residbuf; diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc index e8ee43525d..ac9e1e95ad 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc @@ -76,7 +76,7 @@ waterfall_sink_c_impl::waterfall_sink_c_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize * sizeof(float)); @@ -384,7 +384,7 @@ void waterfall_sink_c_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_fft_shift.resize(d_fftsize); diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h index b5d2514964..add30af47d 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.h +++ b/gr-qtgui/lib/waterfall_sink_c_impl.h @@ -44,7 +44,7 @@ private: const pmt::pmt_t d_port_bw; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; std::vector<gr_complex*> d_residbufs; diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc index 86ec9470f8..b552f490ef 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc @@ -74,7 +74,7 @@ waterfall_sink_f_impl::waterfall_sink_f_impl(int fftsize, // this is usually desired when plotting d_shift = true; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_fbuf = (float*)volk_malloc(d_fftsize * sizeof(float), volk_get_alignment()); memset(d_fbuf, 0, d_fftsize * sizeof(float)); @@ -390,7 +390,7 @@ void waterfall_sink_f_impl::fftresize() // Reset FFTW plan for new size delete d_fft; - d_fft = new fft::fft_complex(d_fftsize, true); + d_fft = new fft::fft_complex_fwd(d_fftsize); d_fft_shift.resize(d_fftsize); diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h index d2bb016659..d206825d8c 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.h +++ b/gr-qtgui/lib/waterfall_sink_f_impl.h @@ -44,7 +44,7 @@ private: const pmt::pmt_t d_port_bw; bool d_shift; - fft::fft_complex* d_fft; + fft::fft_complex_fwd* d_fft; int d_index; std::vector<float*> d_residbufs; |