summaryrefslogtreecommitdiff
path: root/gr-fft
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fft')
-rw-r--r--gr-fft/grc/fft_fft_vxx.block.yml5
-rw-r--r--gr-fft/include/gnuradio/fft/CMakeLists.txt3
-rw-r--r--gr-fft/include/gnuradio/fft/fft.h137
-rw-r--r--gr-fft/include/gnuradio/fft/fft_v.h (renamed from gr-fft/include/gnuradio/fft/fft_vcc.h)16
-rw-r--r--gr-fft/include/gnuradio/fft/fft_vfc.h72
-rw-r--r--gr-fft/lib/CMakeLists.txt3
-rw-r--r--gr-fft/lib/ctrlport_probe_psd_impl.cc2
-rw-r--r--gr-fft/lib/ctrlport_probe_psd_impl.h2
-rw-r--r--gr-fft/lib/fft.cc149
-rw-r--r--gr-fft/lib/fft_v_fftw.cc217
-rw-r--r--gr-fft/lib/fft_v_fftw.h (renamed from gr-fft/lib/fft_vcc_fftw.h)28
-rw-r--r--gr-fft/lib/fft_vcc_fftw.cc125
-rw-r--r--gr-fft/lib/fft_vfc_fftw.cc94
-rw-r--r--gr-fft/lib/fft_vfc_fftw.h45
-rw-r--r--gr-fft/python/fft/CMakeLists.txt2
-rw-r--r--gr-fft/python/fft/__init__.py3
-rw-r--r--gr-fft/python/fft/bindings/CMakeLists.txt4
-rw-r--r--gr-fft/python/fft/bindings/docstrings/fft_pydoc_template.h108
-rw-r--r--gr-fft/python/fft/bindings/docstrings/fft_v_pydoc_template.h15
-rw-r--r--gr-fft/python/fft/bindings/docstrings/fft_vcc_pydoc_template.h36
-rw-r--r--gr-fft/python/fft/bindings/docstrings/fft_vfc_pydoc_template.h36
-rw-r--r--gr-fft/python/fft/bindings/fft_python.cc156
-rw-r--r--gr-fft/python/fft/bindings/fft_v_python.cc (renamed from gr-fft/python/fft/bindings/fft_vcc_python.cc)51
-rw-r--r--gr-fft/python/fft/bindings/fft_vfc_python.cc62
-rw-r--r--gr-fft/python/fft/bindings/python_bindings.cc8
-rw-r--r--gr-fft/python/fft/fft_vcc.py22
-rw-r--r--gr-fft/python/fft/fft_vfc.py22
27 files changed, 410 insertions, 1013 deletions
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)