summaryrefslogtreecommitdiff
path: root/gr-fft
diff options
context:
space:
mode:
authorMarcus Müller <mmueller@gnuradio.org>2019-08-07 21:45:12 +0200
committerMarcus Müller <marcus@hostalia.de>2019-08-09 23:04:28 +0200
commitf7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch)
treee09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-fft
parent78431dc6941e3acc67c858277dfe4a0ed583643c (diff)
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-fft')
-rw-r--r--gr-fft/include/gnuradio/fft/api.h4
-rw-r--r--gr-fft/include/gnuradio/fft/ctrlport_probe_psd.h55
-rw-r--r--gr-fft/include/gnuradio/fft/fft.h286
-rw-r--r--gr-fft/include/gnuradio/fft/fft_shift.h61
-rw-r--r--gr-fft/include/gnuradio/fft/fft_vcc.h97
-rw-r--r--gr-fft/include/gnuradio/fft/fft_vfc.h94
-rw-r--r--gr-fft/include/gnuradio/fft/goertzel.h62
-rw-r--r--gr-fft/include/gnuradio/fft/goertzel_fc.h35
-rw-r--r--gr-fft/include/gnuradio/fft/window.h554
-rw-r--r--gr-fft/lib/ctrlport_probe_psd_impl.cc236
-rw-r--r--gr-fft/lib/ctrlport_probe_psd_impl.h51
-rw-r--r--gr-fft/lib/fft.cc574
-rw-r--r--gr-fft/lib/fft_vcc_fftw.cc208
-rw-r--r--gr-fft/lib/fft_vcc_fftw.h58
-rw-r--r--gr-fft/lib/fft_vfc_fftw.cc140
-rw-r--r--gr-fft/lib/fft_vfc_fftw.h55
-rw-r--r--gr-fft/lib/goertzel.cc82
-rw-r--r--gr-fft/lib/goertzel_fc_impl.cc85
-rw-r--r--gr-fft/lib/goertzel_fc_impl.h41
-rw-r--r--gr-fft/lib/qa_fft_shift.cc28
-rw-r--r--gr-fft/lib/window.cc620
21 files changed, 1674 insertions, 1752 deletions
diff --git a/gr-fft/include/gnuradio/fft/api.h b/gr-fft/include/gnuradio/fft/api.h
index ce2a49f4be..a498012e04 100644
--- a/gr-fft/include/gnuradio/fft/api.h
+++ b/gr-fft/include/gnuradio/fft/api.h
@@ -25,9 +25,9 @@
#include <gnuradio/attributes.h>
#ifdef gnuradio_fft_EXPORTS
-# define FFT_API __GR_ATTR_EXPORT
+#define FFT_API __GR_ATTR_EXPORT
#else
-# define FFT_API __GR_ATTR_IMPORT
+#define FFT_API __GR_ATTR_IMPORT
#endif
#endif /* INCLUDED_FFT_API_H */
diff --git a/gr-fft/include/gnuradio/fft/ctrlport_probe_psd.h b/gr-fft/include/gnuradio/fft/ctrlport_probe_psd.h
index 5c872922c0..21438d5fa8 100644
--- a/gr-fft/include/gnuradio/fft/ctrlport_probe_psd.h
+++ b/gr-fft/include/gnuradio/fft/ctrlport_probe_psd.h
@@ -27,40 +27,39 @@
#include <gnuradio/sync_block.h>
namespace gr {
- namespace fft {
+namespace fft {
+
+/*!
+ * \brief A ControlPort probe to export vectors of signals.
+ * \ingroup measurement_tools_blk
+ * \ingroup controlport_blk
+ *
+ * \details
+ * This block acts as a sink in the flowgraph but also exports
+ * vectors of complex samples over ControlPort. This block holds
+ * the latest \p len number of complex samples so that every query
+ * by a ControlPort client will get the same length vector.
+ */
+class FFT_API ctrlport_probe_psd : virtual public gr::sync_block
+{
+public:
+ typedef boost::shared_ptr<ctrlport_probe_psd> sptr;
/*!
- * \brief A ControlPort probe to export vectors of signals.
- * \ingroup measurement_tools_blk
- * \ingroup controlport_blk
- *
- * \details
- * This block acts as a sink in the flowgraph but also exports
- * vectors of complex samples over ControlPort. This block holds
- * the latest \p len number of complex samples so that every query
- * by a ControlPort client will get the same length vector.
+ * \brief Make a ControlPort probe block.
+ * \param id A string ID to name the probe over ControlPort.
+ * \param desc A string describing the probe.
+ * \param len Number of samples to transmit.
*/
- class FFT_API ctrlport_probe_psd : virtual public gr::sync_block
- {
- public:
- typedef boost::shared_ptr<ctrlport_probe_psd> sptr;
+ static sptr make(const std::string& id, const std::string& desc, int len);
- /*!
- * \brief Make a ControlPort probe block.
- * \param id A string ID to name the probe over ControlPort.
- * \param desc A string describing the probe.
- * \param len Number of samples to transmit.
- */
- static sptr make(const std::string &id, const std::string &desc, int len);
+ virtual std::vector<gr_complex> get() = 0;
- virtual std::vector<gr_complex> get() = 0;
+ virtual void set_length(int len) = 0;
+ virtual int length() const = 0;
+};
- virtual void set_length(int len) = 0;
- virtual int length() const = 0;
- };
-
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE_PSD_H */
-
diff --git a/gr-fft/include/gnuradio/fft/fft.h b/gr-fft/include/gnuradio/fft/fft.h
index 81cd51de21..d6f52d4c7d 100644
--- a/gr-fft/include/gnuradio/fft/fft.h
+++ b/gr-fft/include/gnuradio/fft/fft.h
@@ -32,168 +32,172 @@
#include <boost/thread.hpp>
namespace gr {
- namespace fft {
+namespace fft {
- /*! \brief Helper function for allocating complex* buffers
+/*! \brief Helper function for allocating complex* buffers
+ */
+FFT_API gr_complex* malloc_complex(int size);
+
+/*! \brief Helper function for allocating float* buffers
+ */
+FFT_API float* malloc_float(int size);
+
+/*! \brief Helper function for allocating double* buffers
+ */
+FFT_API double* malloc_double(int size);
+
+/*! \brief Helper function for freeing fft buffers
+ */
+FFT_API void free(void* b);
+
+/*!
+ * \brief Export reference to planner mutex for those apps that
+ * want to use FFTW w/o using the fft_impl_fftw* classes.
+ */
+class FFT_API planner
+{
+public:
+ typedef boost::mutex::scoped_lock scoped_lock;
+ /*!
+ * Return reference to planner mutex
+ */
+ static boost::mutex& mutex();
+};
+
+/*!
+ * \brief FFT: complex in, complex out
+ * \ingroup misc
+ */
+class FFT_API fft_complex
+{
+ int d_fft_size;
+ int d_nthreads;
+ gr_complex* d_inbuf;
+ gr_complex* d_outbuf;
+ void* d_plan;
+
+public:
+ fft_complex(int fft_size, bool forward = true, int nthreads = 1);
+ 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() const { return d_inbuf; }
+ gr_complex* get_outbuf() const { return d_outbuf; }
+
+ int inbuf_length() const { return d_fft_size; }
+ int outbuf_length() const { return d_fft_size; }
+
+ /*!
+ * Set the number of threads to use for caclulation.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * Get the number of threads being used by FFTW
*/
- FFT_API gr_complex* malloc_complex(int size);
+ int nthreads() const { return d_nthreads; }
- /*! \brief Helper function for allocating float* buffers
+ /*!
+ * compute FFT. The input comes from inbuf, the output is placed in
+ * outbuf.
+ */
+ void execute();
+};
+
+/*!
+ * \brief FFT: real in, complex out
+ * \ingroup misc
+ */
+class FFT_API fft_real_fwd
+{
+ int d_fft_size;
+ int d_nthreads;
+ float* d_inbuf;
+ gr_complex* d_outbuf;
+ void* d_plan;
+
+public:
+ fft_real_fwd(int fft_size, int nthreads = 1);
+ 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.
*/
- FFT_API float* malloc_float(int size);
+ float* get_inbuf() const { return d_inbuf; }
+ gr_complex* get_outbuf() const { return d_outbuf; }
- /*! \brief Helper function for allocating double* buffers
+ int inbuf_length() const { return d_fft_size; }
+ int outbuf_length() const { return d_fft_size / 2 + 1; }
+
+ /*!
+ * Set the number of threads to use for caclulation.
*/
- FFT_API double* malloc_double(int size);
+ void set_nthreads(int n);
- /*! \brief Helper function for freeing fft buffers
+ /*!
+ * Get the number of threads being used by FFTW
*/
- FFT_API void free(void *b);
+ int nthreads() const { return d_nthreads; }
/*!
- * \brief Export reference to planner mutex for those apps that
- * want to use FFTW w/o using the fft_impl_fftw* classes.
+ * compute FFT. The input comes from inbuf, the output is placed in
+ * outbuf.
+ */
+ void execute();
+};
+
+/*!
+ * \brief FFT: complex in, float out
+ * \ingroup misc
+ */
+class FFT_API fft_real_rev
+{
+ int d_fft_size;
+ int d_nthreads;
+ gr_complex* d_inbuf;
+ float* d_outbuf;
+ void* d_plan;
+
+public:
+ fft_real_rev(int fft_size, int nthreads = 1);
+ virtual ~fft_real_rev();
+
+ /*
+ * These return pointers to buffers owned by fft_impl_fft_real_rev
+ * into which input and output take place. It's done this way in
+ * order to ensure optimal alignment for SIMD instructions.
*/
- class FFT_API planner {
- public:
- typedef boost::mutex::scoped_lock scoped_lock;
- /*!
- * Return reference to planner mutex
- */
- static boost::mutex &mutex();
- };
+ gr_complex* get_inbuf() const { return d_inbuf; }
+ float* get_outbuf() const { return d_outbuf; }
+
+ int inbuf_length() const { return d_fft_size / 2 + 1; }
+ int outbuf_length() const { return d_fft_size; }
/*!
- * \brief FFT: complex in, complex out
- * \ingroup misc
+ * Set the number of threads to use for caclulation.
*/
- class FFT_API fft_complex {
- int d_fft_size;
- int d_nthreads;
- gr_complex *d_inbuf;
- gr_complex *d_outbuf;
- void *d_plan;
-
- public:
- fft_complex(int fft_size, bool forward = true, int nthreads=1);
- 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() const { return d_inbuf; }
- gr_complex *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size; }
- int outbuf_length() const { return d_fft_size; }
-
- /*!
- * 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; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
+ void set_nthreads(int n);
/*!
- * \brief FFT: real in, complex out
- * \ingroup misc
+ * Get the number of threads being used by FFTW
*/
- class FFT_API fft_real_fwd {
- int d_fft_size;
- int d_nthreads;
- float *d_inbuf;
- gr_complex *d_outbuf;
- void *d_plan;
-
- public:
- fft_real_fwd (int fft_size, int nthreads=1);
- 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() const { return d_inbuf; }
- gr_complex *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size; }
- int outbuf_length() const { return d_fft_size / 2 + 1; }
-
- /*!
- * 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; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
+ int nthreads() const { return d_nthreads; }
/*!
- * \brief FFT: complex in, float out
- * \ingroup misc
+ * compute FFT. The input comes from inbuf, the output is placed in
+ * outbuf.
*/
- class FFT_API fft_real_rev {
- int d_fft_size;
- int d_nthreads;
- gr_complex *d_inbuf;
- float *d_outbuf;
- void *d_plan;
-
- public:
- fft_real_rev(int fft_size, int nthreads=1);
- virtual ~fft_real_rev();
-
- /*
- * These return pointers to buffers owned by fft_impl_fft_real_rev
- * 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() const { return d_inbuf; }
- float *get_outbuf() const { return d_outbuf; }
-
- int inbuf_length() const { return d_fft_size / 2 + 1; }
- int outbuf_length() const { return d_fft_size; }
-
- /*!
- * 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; }
-
- /*!
- * compute FFT. The input comes from inbuf, the output is placed in
- * outbuf.
- */
- void execute();
- };
-
- } /* namespace fft */
+ void execute();
+};
+
+} /* namespace fft */
} /*namespace gr */
#endif /* _FFT_FFT_H_ */
diff --git a/gr-fft/include/gnuradio/fft/fft_shift.h b/gr-fft/include/gnuradio/fft/fft_shift.h
index 1ee08915b9..a0fd5a6e2e 100644
--- a/gr-fft/include/gnuradio/fft/fft_shift.h
+++ b/gr-fft/include/gnuradio/fft/fft_shift.h
@@ -30,52 +30,55 @@
namespace gr {
namespace fft {
- /*! \brief reorder FFT results which are ordered from 0 to 1 in normalized frequency
- * to -0.5 to 0.5 by cyclic shift
- */
- template<typename T>
- class fft_shift {
- public:
+/*! \brief reorder FFT results which are ordered from 0 to 1 in normalized frequency
+ * to -0.5 to 0.5 by cyclic shift
+ */
+template <typename T>
+class fft_shift
+{
+public:
fft_shift(size_t fft_length)
- : d_fftlen(fft_length)
- , d_lenpos(fft_length/2 + (fft_length%2))
- , d_lenneg(fft_length/2)
- , d_buf(fft_length) {}
+ : d_fftlen(fft_length),
+ d_lenpos(fft_length / 2 + (fft_length % 2)),
+ d_lenneg(fft_length / 2),
+ d_buf(fft_length)
+ {
+ }
/*! performs the cyclic shift on a vector v
*/
- void shift(std::vector<T>& v) {
- shift(&v.front(), v.size());
- }
+ void shift(std::vector<T>& v) { shift(&v.front(), v.size()); }
/*! performs the cyclic shift on an array
*/
- void shift(T* data, size_t fft_len) {
- resize(fft_len);
- std::copy_n(data, d_lenpos, d_buf.begin());
- std::copy_n(data+d_lenpos, d_lenneg, data);
- std::copy_n(d_buf.begin(), d_lenpos, data+d_lenneg);
+ void shift(T* data, size_t fft_len)
+ {
+ resize(fft_len);
+ std::copy_n(data, d_lenpos, d_buf.begin());
+ std::copy_n(data + d_lenpos, d_lenneg, data);
+ std::copy_n(d_buf.begin(), d_lenpos, data + d_lenneg);
}
/*! if needed adjusts the buffer size to a new fft length
*/
- void resize(size_t fft_length) {
- if (d_fftlen == fft_length)
- return;
- d_fftlen = fft_length;
- d_lenpos = d_fftlen/2 + (d_fftlen%2);
- d_lenneg = d_fftlen/2;
- assert(d_lenpos + d_lenneg == d_fftlen);
- d_buf.resize(d_lenpos);
+ void resize(size_t fft_length)
+ {
+ if (d_fftlen == fft_length)
+ return;
+ d_fftlen = fft_length;
+ d_lenpos = d_fftlen / 2 + (d_fftlen % 2);
+ d_lenneg = d_fftlen / 2;
+ assert(d_lenpos + d_lenneg == d_fftlen);
+ d_buf.resize(d_lenpos);
}
- protected:
- private:
+protected:
+private:
size_t d_fftlen; // FFT length
size_t d_lenpos; // number of FFT bins with positive frequencies
size_t d_lenneg; // number of FFT bins with negative frequencies
std::vector<T> d_buf; // buffer used for cyclic shift
- } ;
+};
} // namespace fft
} // namespace gr
diff --git a/gr-fft/include/gnuradio/fft/fft_vcc.h b/gr-fft/include/gnuradio/fft/fft_vcc.h
index 03e82a9989..a10398465e 100644
--- a/gr-fft/include/gnuradio/fft/fft_vcc.h
+++ b/gr-fft/include/gnuradio/fft/fft_vcc.h
@@ -27,60 +27,61 @@
#include <gnuradio/sync_block.h>
namespace gr {
- namespace fft {
+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 arround) will be scaled i.e.
- * \f$FFT\{ \, IFFT\{x\} \,\} = N \cdot x \neq x\f$.
- *
- * \see http://www.fftw.org/faq/section3.html#whyscaled
+/*!
+ * \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 arround) 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_vcc : virtual public sync_block
+{
+public:
+ // gr::fft::fft_vcc::sptr
+ typedef boost::shared_ptr<fft_vcc> 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.
*/
- class FFT_API fft_vcc : virtual public sync_block
- {
- public:
-
- // gr::fft::fft_vcc::sptr
- typedef boost::shared_ptr<fft_vcc> 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);
+ static sptr make(int fft_size,
+ bool forward,
+ const std::vector<float>& window,
+ bool shift = false,
+ int nthreads = 1);
- virtual void set_nthreads(int n) = 0;
+ virtual void set_nthreads(int n) = 0;
- virtual int nthreads() const = 0;
+ virtual int nthreads() const = 0;
- virtual bool set_window(const std::vector<float> &window) = 0;
- };
+ virtual bool set_window(const std::vector<float>& window) = 0;
+};
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_FFT_VCC_H */
diff --git a/gr-fft/include/gnuradio/fft/fft_vfc.h b/gr-fft/include/gnuradio/fft/fft_vfc.h
index e5ec9bf3ee..8b194ec8e3 100644
--- a/gr-fft/include/gnuradio/fft/fft_vfc.h
+++ b/gr-fft/include/gnuradio/fft/fft_vfc.h
@@ -27,60 +27,58 @@
#include <gnuradio/sync_block.h>
namespace gr {
- namespace fft {
+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 arround) 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 boost::shared_ptr<fft_vfc> sptr;
+/*!
+ * \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 arround) 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 boost::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);
+ /*! \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 void set_nthreads(int n) = 0;
- virtual int nthreads() const = 0;
+ virtual int nthreads() const = 0;
- virtual bool set_window(const std::vector<float> &window) = 0;
- };
+ virtual bool set_window(const std::vector<float>& window) = 0;
+};
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_FFT_VFC_H */
diff --git a/gr-fft/include/gnuradio/fft/goertzel.h b/gr-fft/include/gnuradio/fft/goertzel.h
index ac77e7d2dd..38b03a1b25 100644
--- a/gr-fft/include/gnuradio/fft/goertzel.h
+++ b/gr-fft/include/gnuradio/fft/goertzel.h
@@ -27,37 +27,37 @@
#include <gnuradio/types.h>
namespace gr {
- namespace fft {
-
- /*!
- * \brief Implements Goertzel single-bin DFT calculation
- * \ingroup misc
- */
- class FFT_API goertzel
- {
- public:
- goertzel(int rate, int len, float freq);
-
- void set_params(int rate, int len, float freq);
-
- // Process a input array
- gr_complex batch(float *in);
-
- // Process sample by sample
- void input(const float &in);
- gr_complex output();
- bool ready() const { return d_processed == d_len; }
-
- private:
- float d_d1;
- float d_d2;
- float d_wr;
- float d_wi;
- int d_len;
- int d_processed;
- };
-
- } /* namespace fft */
+namespace fft {
+
+/*!
+ * \brief Implements Goertzel single-bin DFT calculation
+ * \ingroup misc
+ */
+class FFT_API goertzel
+{
+public:
+ goertzel(int rate, int len, float freq);
+
+ void set_params(int rate, int len, float freq);
+
+ // Process a input array
+ gr_complex batch(float* in);
+
+ // Process sample by sample
+ void input(const float& in);
+ gr_complex output();
+ bool ready() const { return d_processed == d_len; }
+
+private:
+ float d_d1;
+ float d_d2;
+ float d_wr;
+ float d_wi;
+ int d_len;
+ int d_processed;
+};
+
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_IMPL_GOERTZEL_H */
diff --git a/gr-fft/include/gnuradio/fft/goertzel_fc.h b/gr-fft/include/gnuradio/fft/goertzel_fc.h
index daa0c5ec26..75d97380fd 100644
--- a/gr-fft/include/gnuradio/fft/goertzel_fc.h
+++ b/gr-fft/include/gnuradio/fft/goertzel_fc.h
@@ -27,31 +27,30 @@
#include <gnuradio/sync_decimator.h>
namespace gr {
- namespace fft {
+namespace fft {
- /*!
- * \brief Goertzel single-bin DFT calculation.
- * \ingroup fourier_analysis_blk
- */
- class FFT_API goertzel_fc : virtual public sync_decimator
- {
- public:
-
- // gr::fft::goertzel_fc::sptr
- typedef boost::shared_ptr<goertzel_fc> sptr;
+/*!
+ * \brief Goertzel single-bin DFT calculation.
+ * \ingroup fourier_analysis_blk
+ */
+class FFT_API goertzel_fc : virtual public sync_decimator
+{
+public:
+ // gr::fft::goertzel_fc::sptr
+ typedef boost::shared_ptr<goertzel_fc> sptr;
- static sptr make(int rate, int len, float freq);
+ static sptr make(int rate, int len, float freq);
- virtual void set_freq (float freq) = 0;
+ virtual void set_freq(float freq) = 0;
- virtual void set_rate (int rate) = 0;
+ virtual void set_rate(int rate) = 0;
- virtual float freq() = 0;
+ virtual float freq() = 0;
- virtual int rate() = 0;
- };
+ virtual int rate() = 0;
+};
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_GOERTZEL_FC_H */
diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h
index 564753a61c..d6ccf9ff7c 100644
--- a/gr-fft/include/gnuradio/fft/window.h
+++ b/gr-fft/include/gnuradio/fft/window.h
@@ -29,284 +29,288 @@
#include <gnuradio/gr_complex.h>
namespace gr {
- namespace fft {
-
- class FFT_API window {
- public:
-
- enum win_type {
- WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
- WIN_HANN = 1, //!< Hann window; max attenuation 44 dB
- WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB
- WIN_RECTANGULAR = 3, //!< Basic rectangular window; max attenuation 21 dB
- WIN_KAISER = 4, //!< Kaiser window; max attenuation see window::max_attenuation
+namespace fft {
+
+class FFT_API window
+{
+public:
+ enum win_type {
+ WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
+ WIN_HANN = 1, //!< Hann window; max attenuation 44 dB
+ WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB
+ WIN_RECTANGULAR = 3, //!< Basic rectangular window; max attenuation 21 dB
+ WIN_KAISER = 4, //!< Kaiser window; max attenuation see window::max_attenuation
WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window; max attenuation 92 dB
- WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
- WIN_BARTLETT = 6, //!< Barlett (triangular) window; max attenuation 26 dB
- WIN_FLATTOP = 7, //!< flat top window; useful in FFTs; max attenuation 93 dB
- };
-
- /*!
- * \brief Given a window::win_type, this tells you the maximum
- * attenuation you can expect.
- *
- * \details
- * For most windows, this is a set value. For the Kaiser window,
- * the attenuation is based on the value of beta. The actual
- * relationship is a piece-wise exponential relationship to
- * calculate beta from the desired attenuation and can be found
- * on page 542 of Oppenheim and Schafer (Discrete-Time Signal
- * Processing, 3rd edition). To simplify this function to solve
- * for A given beta, we use a linear form that is exact for
- * attenuation >= 50 dB.
- *
- * For an attenuation of 50 dB, beta = 4.55.
- *
- * For an attenuation of 70 dB, beta = 6.76.
- *
- * \param type The window::win_type enumeration of the window type.
- * \param beta Beta value only used for the Kaiser window.
- */
- static double max_attenuation(win_type type, double beta=6.76);
-
- /*!
- * \brief Helper function to build cosine-based windows. 3-coefficient version.
- */
- static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2);
-
- /*!
- * \brief Helper function to build cosine-based windows. 4-coefficient version.
- */
- static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2, float c3);
-
- /*!
- * \brief Helper function to build cosine-based windows. 5-coefficient version.
- */
- static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4);
-
- /*!
- * \brief Build a rectangular window.
- *
- * Taps are flat across the window.
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> rectangular(int ntaps);
-
- /*!
- * \brief Build a Hamming window.
- *
- * See:
- * <pre>
- * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
- * Signal Processing," Upper Saddle River, N.J.: Prentice
- * Hall, 2010, pp. 535-538.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> hamming(int ntaps);
-
- /*!
- * \brief Build a Hann window (sometimes known as Hanning).
- *
- * See:
- * <pre>
- * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
- * Signal Processing," Upper Saddle River, N.J.: Prentice
- * Hall, 2010, pp. 535-538.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> hann(int ntaps);
-
- /*!
- * \brief Alias to build a Hann window.
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> hanning(int ntaps);
-
- /*!
- * \brief Build an exact Blackman window.
- *
- * See:
- * <pre>
- * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
- * Signal Processing," Upper Saddle River, N.J.: Prentice
- * Hall, 2010, pp. 535-538.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> blackman(int ntaps);
-
- /*!
- * \brief Build Blackman window, variation 1.
- */
- static std::vector<float> blackman2(int ntaps);
-
- /*!
- * \brief Build Blackman window, variation 2.
- */
- static std::vector<float> blackman3(int ntaps);
-
- /*!
- * \brief Build Blackman window, variation 3.
- */
- static std::vector<float> blackman4(int ntaps);
-
- /*!
- * \brief Build a Blackman-harris window with a given attenuation.
- *
- * <pre>
- * f. j. harris, "On the use of windows for harmonic analysis
- * with the discrete Fourier transforms," Proc. IEEE, Vol. 66,
- * ppg. 51-83, Jan. 1978.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
-
- * \param atten Attenuation factor. Must be [61, 67, 74, 92].
- * See the above paper for details.
- */
- static std::vector<float> blackman_harris(int ntaps, int atten=92);
-
- /*!
- * Alias to gr::fft::window::blakcman_harris.
- */
- static std::vector<float> blackmanharris(int ntaps, int atten=92);
-
- /*!
- * \brief Build a Nuttall (or Blackman-Nuttall) window.
- *
- * See: http://en.wikipedia.org/wiki/Window_function#Blackman.E2.80.93Nuttall_window
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> nuttall(int ntaps);
-
- /*!
- * Deprecated: use nuttall window instead.
- */
- static std::vector<float> nuttal(int ntaps);
-
- /*!
- * \brief Alias to the Nuttall window.
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> blackman_nuttall(int ntaps);
-
- /*!
- * Deprecated: use blackman_nuttall window instead.
- */
- static std::vector<float> blackman_nuttal(int ntaps);
-
- /*!
- * \brief Build a Nuttall continuous first derivative window.
- *
- * See: http://en.wikipedia.org/wiki/Window_function#Nuttall_window.2C_continuous_first_derivative
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> nuttall_cfd(int ntaps);
-
- /*!
- * Deprecated: use nuttall_cfd window instead.
- */
- static std::vector<float> nuttal_cfd(int ntaps);
-
- /*!
- * \brief Build a flat top window.
- *
- * See: http://en.wikipedia.org/wiki/Window_function#Flat_top_window
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> flattop(int ntaps);
-
- /*!
- * \brief Build a Kaiser window with a given beta.
- *
- * See:
- * <pre>
- * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
- * Signal Processing," Upper Saddle River, N.J.: Prentice
- * Hall, 2010, pp. 541-545.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- * \param beta Shaping parameter of the window. See the
- * discussion in Oppenheim and Schafer.
- */
- static std::vector<float> kaiser(int ntaps, double beta);
-
- /*!
- * \brief Build a Barlett (triangular) window.
- *
- * See:
- * <pre>
- * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
- * Signal Processing," Upper Saddle River, N.J.: Prentice
- * Hall, 2010, pp. 535-538.
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> bartlett(int ntaps);
-
- static std::vector<float> welch(int ntaps);
-
- /*!
- * \brief Build a Parzen (or de la Valle-Poussin) window.
- *
- * See:
- * <pre>
- * A. D. Poularikas, "Handbook of Formulas and Tables for
- * Signal Processing," Springer, Oct 28, 1998
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> parzen(int ntaps);
-
- /*!
- * \brief Build an exponential window with a given decay.
- *
- * See: http://en.wikipedia.org/wiki/Window_function#Exponential_or_Poisson_window
- *
- * \param ntaps Number of coefficients in the window.
- * \param d Decay of \p d dB over half the window length.
- */
- static std::vector<float> exponential(int ntaps, double d);
-
- /*!
- * \brief Build a Riemann window.
- *
- * See:
- * <pre>
- * A. D. Poularikas, "Handbook of Formulas and Tables for
- * Signal Processing," Springer, Oct 28, 1998
- * </pre>
- *
- * \param ntaps Number of coefficients in the window.
- */
- static std::vector<float> riemann(int ntaps);
-
- /*!
- * \brief Build a window using gr::fft::win_type to index the
- * type of window desired.
- *
- * \param type a gr::fft::win_type index for the type of window.
- * \param ntaps Number of coefficients in the window.
- * \param beta Used only for building Kaiser windows.
- */
- static std::vector<float> build(win_type type, int ntaps, double beta);
+ WIN_BLACKMAN_HARRIS =
+ 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
+ WIN_BARTLETT = 6, //!< Barlett (triangular) window; max attenuation 26 dB
+ WIN_FLATTOP = 7, //!< flat top window; useful in FFTs; max attenuation 93 dB
};
- } /* namespace fft */
+ /*!
+ * \brief Given a window::win_type, this tells you the maximum
+ * attenuation you can expect.
+ *
+ * \details
+ * For most windows, this is a set value. For the Kaiser window,
+ * the attenuation is based on the value of beta. The actual
+ * relationship is a piece-wise exponential relationship to
+ * calculate beta from the desired attenuation and can be found
+ * on page 542 of Oppenheim and Schafer (Discrete-Time Signal
+ * Processing, 3rd edition). To simplify this function to solve
+ * for A given beta, we use a linear form that is exact for
+ * attenuation >= 50 dB.
+ *
+ * For an attenuation of 50 dB, beta = 4.55.
+ *
+ * For an attenuation of 70 dB, beta = 6.76.
+ *
+ * \param type The window::win_type enumeration of the window type.
+ * \param beta Beta value only used for the Kaiser window.
+ */
+ static double max_attenuation(win_type type, double beta = 6.76);
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 3-coefficient version.
+ */
+ static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2);
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 4-coefficient version.
+ */
+ static std::vector<float>
+ coswindow(int ntaps, float c0, float c1, float c2, float c3);
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 5-coefficient version.
+ */
+ static std::vector<float>
+ coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4);
+
+ /*!
+ * \brief Build a rectangular window.
+ *
+ * Taps are flat across the window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> rectangular(int ntaps);
+
+ /*!
+ * \brief Build a Hamming window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hamming(int ntaps);
+
+ /*!
+ * \brief Build a Hann window (sometimes known as Hanning).
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hann(int ntaps);
+
+ /*!
+ * \brief Alias to build a Hann window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hanning(int ntaps);
+
+ /*!
+ * \brief Build an exact Blackman window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> blackman(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 1.
+ */
+ static std::vector<float> blackman2(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 2.
+ */
+ static std::vector<float> blackman3(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 3.
+ */
+ static std::vector<float> blackman4(int ntaps);
+
+ /*!
+ * \brief Build a Blackman-harris window with a given attenuation.
+ *
+ * <pre>
+ * f. j. harris, "On the use of windows for harmonic analysis
+ * with the discrete Fourier transforms," Proc. IEEE, Vol. 66,
+ * ppg. 51-83, Jan. 1978.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+
+ * \param atten Attenuation factor. Must be [61, 67, 74, 92].
+ * See the above paper for details.
+ */
+ static std::vector<float> blackman_harris(int ntaps, int atten = 92);
+
+ /*!
+ * Alias to gr::fft::window::blakcman_harris.
+ */
+ static std::vector<float> blackmanharris(int ntaps, int atten = 92);
+
+ /*!
+ * \brief Build a Nuttall (or Blackman-Nuttall) window.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Blackman.E2.80.93Nuttall_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> nuttall(int ntaps);
+
+ /*!
+ * Deprecated: use nuttall window instead.
+ */
+ static std::vector<float> nuttal(int ntaps);
+
+ /*!
+ * \brief Alias to the Nuttall window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> blackman_nuttall(int ntaps);
+
+ /*!
+ * Deprecated: use blackman_nuttall window instead.
+ */
+ static std::vector<float> blackman_nuttal(int ntaps);
+
+ /*!
+ * \brief Build a Nuttall continuous first derivative window.
+ *
+ * See:
+ * http://en.wikipedia.org/wiki/Window_function#Nuttall_window.2C_continuous_first_derivative
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> nuttall_cfd(int ntaps);
+
+ /*!
+ * Deprecated: use nuttall_cfd window instead.
+ */
+ static std::vector<float> nuttal_cfd(int ntaps);
+
+ /*!
+ * \brief Build a flat top window.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Flat_top_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> flattop(int ntaps);
+
+ /*!
+ * \brief Build a Kaiser window with a given beta.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 541-545.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ * \param beta Shaping parameter of the window. See the
+ * discussion in Oppenheim and Schafer.
+ */
+ static std::vector<float> kaiser(int ntaps, double beta);
+
+ /*!
+ * \brief Build a Barlett (triangular) window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> bartlett(int ntaps);
+
+ static std::vector<float> welch(int ntaps);
+
+ /*!
+ * \brief Build a Parzen (or de la Valle-Poussin) window.
+ *
+ * See:
+ * <pre>
+ * A. D. Poularikas, "Handbook of Formulas and Tables for
+ * Signal Processing," Springer, Oct 28, 1998
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> parzen(int ntaps);
+
+ /*!
+ * \brief Build an exponential window with a given decay.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Exponential_or_Poisson_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ * \param d Decay of \p d dB over half the window length.
+ */
+ static std::vector<float> exponential(int ntaps, double d);
+
+ /*!
+ * \brief Build a Riemann window.
+ *
+ * See:
+ * <pre>
+ * A. D. Poularikas, "Handbook of Formulas and Tables for
+ * Signal Processing," Springer, Oct 28, 1998
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> riemann(int ntaps);
+
+ /*!
+ * \brief Build a window using gr::fft::win_type to index the
+ * type of window desired.
+ *
+ * \param type a gr::fft::win_type index for the type of window.
+ * \param ntaps Number of coefficients in the window.
+ * \param beta Used only for building Kaiser windows.
+ */
+ static std::vector<float> build(win_type type, int ntaps, double beta);
+};
+
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_WINDOW_H */
diff --git a/gr-fft/lib/ctrlport_probe_psd_impl.cc b/gr-fft/lib/ctrlport_probe_psd_impl.cc
index a12341e931..cb172666c9 100644
--- a/gr-fft/lib/ctrlport_probe_psd_impl.cc
+++ b/gr-fft/lib/ctrlport_probe_psd_impl.cc
@@ -28,139 +28,139 @@
#include <gnuradio/io_signature.h>
namespace gr {
- namespace fft {
-
- ctrlport_probe_psd::sptr
- ctrlport_probe_psd::make(const std::string &id,
- const std::string &desc, int len)
- {
- return gnuradio::get_initial_sptr
- (new ctrlport_probe_psd_impl(id, desc, len));
- }
-
- ctrlport_probe_psd_impl::ctrlport_probe_psd_impl(const std::string &id,
- const std::string &desc, int len)
- : gr::sync_block("probe_psd",
- gr::io_signature::make(1, 1, sizeof(gr_complex)),
- gr::io_signature::make(0, 0, 0)),
- d_id(id), d_desc(desc), d_len(len),
- d_fft(len, true, 1)
- {
- set_length(len);
- }
-
- ctrlport_probe_psd_impl::~ctrlport_probe_psd_impl()
- {
- }
-
- void
- ctrlport_probe_psd_impl::forecast(int noutput_items,
- gr_vector_int &ninput_items_required)
- {
- // make sure all inputs have noutput_items available
- unsigned ninputs = ninput_items_required.size();
- for(unsigned i = 0; i < ninputs; i++)
+namespace fft {
+
+ctrlport_probe_psd::sptr
+ctrlport_probe_psd::make(const std::string& id, const std::string& desc, int len)
+{
+ return gnuradio::get_initial_sptr(new ctrlport_probe_psd_impl(id, desc, len));
+}
+
+ctrlport_probe_psd_impl::ctrlport_probe_psd_impl(const std::string& id,
+ const std::string& desc,
+ int len)
+ : gr::sync_block("probe_psd",
+ gr::io_signature::make(1, 1, sizeof(gr_complex)),
+ gr::io_signature::make(0, 0, 0)),
+ d_id(id),
+ d_desc(desc),
+ d_len(len),
+ d_fft(len, true, 1)
+{
+ set_length(len);
+}
+
+ctrlport_probe_psd_impl::~ctrlport_probe_psd_impl() {}
+
+void ctrlport_probe_psd_impl::forecast(int noutput_items,
+ gr_vector_int& ninput_items_required)
+{
+ // make sure all inputs have noutput_items available
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++)
ninput_items_required[i] = d_len;
+}
+
+// boost::shared_mutex mutex_buffer;
+// mutable boost::mutex mutex_notify;
+// boost::condition_variable condition_buffer_ready;
+std::vector<gr_complex> ctrlport_probe_psd_impl::get()
+{
+ mutex_buffer.lock();
+ d_buffer.clear();
+ mutex_buffer.unlock();
+
+ // wait for condition
+ boost::mutex::scoped_lock lock(mutex_notify);
+ condition_buffer_ready.wait(lock);
+
+ mutex_buffer.lock();
+
+ memcpy(d_fft.get_inbuf(), &d_buffer[0], d_len * sizeof(gr_complex));
+ d_fft.execute();
+ std::vector<gr_complex> buf_copy;
+
+ buf_copy.resize(d_len);
+
+ gr_complex* out = d_fft.get_outbuf();
+ for (size_t i = 0; i < d_len; i++) {
+ size_t idx = (i + d_len / 2) % d_len;
+ float x = i / (d_len - 1.0f) - 0.5;
+ buf_copy[i] = gr_complex(x, 10 * log10((out[idx] * std::conj(out[idx])).real()));
}
-
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
- std::vector<gr_complex>
- ctrlport_probe_psd_impl::get()
- {
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
-
- memcpy(d_fft.get_inbuf(), &d_buffer[0], d_len*sizeof(gr_complex));
- d_fft.execute();
- std::vector<gr_complex> buf_copy;
-
- buf_copy.resize(d_len);
-
- gr_complex* out = d_fft.get_outbuf();
- for(size_t i=0; i<d_len; i++){
- size_t idx = (i + d_len/2)%d_len;
- float x = i/(d_len-1.0f)-0.5;
- buf_copy[i] = gr_complex(x, 10*log10( (out[idx]*std::conj(out[idx])).real() ) );
- }
- mutex_buffer.unlock();
- return buf_copy;
- }
-
- void
- ctrlport_probe_psd_impl::set_length(int len)
- {
- if(len > 8191) {
- std::cerr << "probe_psd: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ mutex_buffer.unlock();
+ return buf_copy;
+}
+
+void ctrlport_probe_psd_impl::set_length(int len)
+{
+ if (len > 8191) {
+ std::cerr << "probe_psd: length " << len << " exceeds maximum buffer size of 8191"
+ << std::endl;
len = 8191;
- }
-
- d_len = len;
- d_buffer.reserve(d_len);
}
- int
- ctrlport_probe_psd_impl::length() const
- {
- return (int)d_len;
- }
+ d_len = len;
+ d_buffer.reserve(d_len);
+}
- int
- ctrlport_probe_psd_impl::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];
+int ctrlport_probe_psd_impl::length() const { return (int)d_len; }
- // copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+int ctrlport_probe_psd_impl::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];
+
+ // copy samples to get buffer if we need samples
+ mutex_buffer.lock();
+ if (d_buffer.size() < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min((int)(d_len - d_buffer.size()), noutput_items);
// TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
+ for (int i = 0; i < num_copy; i++) {
+ d_buffer.push_back(in[i]);
}
// notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
+ if (d_buffer.size() == d_len) {
+ condition_buffer_ready.notify_one();
}
- }
- mutex_buffer.unlock();
-
- return noutput_items;
}
+ mutex_buffer.unlock();
- void
- ctrlport_probe_psd_impl::setup_rpc()
- {
+ return noutput_items;
+}
+
+void ctrlport_probe_psd_impl::setup_rpc()
+{
#ifdef GR_CTRLPORT
- int len = static_cast<int>(d_len);
- d_rpc_vars.push_back(
- rpcbasic_sptr(new rpcbasic_register_get<ctrlport_probe_psd, std::vector<std::complex<float> > >(
- alias(), d_id.c_str(), &ctrlport_probe_psd::get,
- pmt::make_c32vector(0,-2),
- pmt::make_c32vector(0,2),
- pmt::make_c32vector(0,0),
- "dB", d_desc.c_str(), RPC_PRIVLVL_MIN,
- DISPXY | DISPOPTSCATTER)));
-
- d_rpc_vars.push_back(
- rpcbasic_sptr(new rpcbasic_register_get<ctrlport_probe_psd, int>(
- alias(), "length", &ctrlport_probe_psd::length,
- pmt::mp(1), pmt::mp(10*len), pmt::mp(len),
- "samples", "get vector length", RPC_PRIVLVL_MIN, DISPNULL)));
+ int len = static_cast<int>(d_len);
+ d_rpc_vars.push_back(rpcbasic_sptr(
+ new rpcbasic_register_get<ctrlport_probe_psd, std::vector<std::complex<float>>>(
+ alias(),
+ d_id.c_str(),
+ &ctrlport_probe_psd::get,
+ pmt::make_c32vector(0, -2),
+ pmt::make_c32vector(0, 2),
+ pmt::make_c32vector(0, 0),
+ "dB",
+ d_desc.c_str(),
+ RPC_PRIVLVL_MIN,
+ DISPXY | DISPOPTSCATTER)));
+
+ d_rpc_vars.push_back(rpcbasic_sptr(
+ new rpcbasic_register_get<ctrlport_probe_psd, int>(alias(),
+ "length",
+ &ctrlport_probe_psd::length,
+ pmt::mp(1),
+ pmt::mp(10 * len),
+ pmt::mp(len),
+ "samples",
+ "get vector length",
+ RPC_PRIVLVL_MIN,
+ DISPNULL)));
// d_rpc_vars.push_back(
// rpcbasic_sptr(new rpcbasic_register_set<ctrlport_probe_psd, int>(
@@ -168,7 +168,7 @@ namespace gr {
// pmt::mp(1), pmt::mp(10*len), pmt::mp(len),
// "samples", "set vector length", RPC_PRIVLVL_MIN, DISPNULL)));
#endif /* GR_CTRLPORT */
- }
+}
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
diff --git a/gr-fft/lib/ctrlport_probe_psd_impl.h b/gr-fft/lib/ctrlport_probe_psd_impl.h
index c8277a4022..58b1f10414 100644
--- a/gr-fft/lib/ctrlport_probe_psd_impl.h
+++ b/gr-fft/lib/ctrlport_probe_psd_impl.h
@@ -29,41 +29,40 @@
#include <gnuradio/fft/fft.h>
namespace gr {
- namespace fft {
+namespace fft {
- class ctrlport_probe_psd_impl : public ctrlport_probe_psd
- {
- private:
- std::string d_id;
- std::string d_desc;
- size_t d_len;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+class ctrlport_probe_psd_impl : public ctrlport_probe_psd
+{
+private:
+ std::string d_id;
+ std::string d_desc;
+ size_t d_len;
+ boost::shared_mutex mutex_buffer;
+ mutable boost::mutex mutex_notify;
+ boost::condition_variable condition_buffer_ready;
- std::vector<gr_complex> d_buffer;
- gr::fft::fft_complex d_fft;
+ std::vector<gr_complex> d_buffer;
+ gr::fft::fft_complex d_fft;
- public:
- ctrlport_probe_psd_impl(const std::string &id, const std::string &desc, int len);
- ~ctrlport_probe_psd_impl();
+public:
+ ctrlport_probe_psd_impl(const std::string& id, const std::string& desc, int len);
+ ~ctrlport_probe_psd_impl();
- void setup_rpc();
+ void setup_rpc();
- void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ void forecast(int noutput_items, gr_vector_int& ninput_items_required);
- std::vector<gr_complex> get();
+ std::vector<gr_complex> get();
- void set_length(int len);
- int length() const;
+ void set_length(int len);
+ int length() const;
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace blocks */
+} // namespace fft
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE_PSD_IMPL_H */
-
diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc
index 718cd0990f..68070d2399 100644
--- a/gr-fft/lib/fft.cc
+++ b/gr-fft/lib/fft.cc
@@ -26,17 +26,19 @@
#include <volk/volk.h>
#include <fftw3.h>
-#ifdef _WIN32 //http://www.fftw.org/install/windows.html#DLLwisdom
-static void my_fftw_write_char(char c, void *f) { fputc(c, (FILE *) f); }
-#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*) (f))
-#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*) (f))
-#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*) (f))
-
-static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); }
-#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*) (f))
-#define fftwf_import_wisdom_from_file(f) fftwf_import_wisdom(my_fftw_read_char, (void*) (f))
-#define fftwl_import_wisdom_from_file(f) fftwl_import_wisdom(my_fftw_read_char, (void*) (f))
-#include <fcntl.h>
+#ifdef _WIN32 // http://www.fftw.org/install/windows.html#DLLwisdom
+static void my_fftw_write_char(char c, void* f) { fputc(c, (FILE*)f); }
+#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*)(f))
+#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*)(f))
+#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*)(f))
+
+static int my_fftw_read_char(void* f) { return fgetc((FILE*)f); }
+#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*)(f))
+#define fftwf_import_wisdom_from_file(f) \
+ fftwf_import_wisdom(my_fftw_read_char, (void*)(f))
+#define fftwl_import_wisdom_from_file(f) \
+ fftwl_import_wisdom(my_fftw_read_char, (void*)(f))
+#include <fcntl.h>
#include <io.h>
#define O_NOCTTY 0
#define O_NONBLOCK 0
@@ -54,349 +56,319 @@ static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); }
namespace fs = boost::filesystem;
namespace gr {
- namespace fft {
- static boost::mutex wisdom_thread_mutex;
- boost::interprocess::file_lock wisdom_lock;
- static bool wisdom_lock_init_done = false; // Modify while holding 'wisdom_thread_mutex'
-
- gr_complex *
- malloc_complex(int size)
- {
- return (gr_complex*) volk_malloc (sizeof (gr_complex)*size, volk_get_alignment ());
- }
-
- float *
- malloc_float(int size)
- {
- return (float*) volk_malloc (sizeof (float)*size, volk_get_alignment ());
- }
+namespace fft {
+static boost::mutex wisdom_thread_mutex;
+boost::interprocess::file_lock wisdom_lock;
+static bool wisdom_lock_init_done = false; // Modify while holding 'wisdom_thread_mutex'
+
+gr_complex* malloc_complex(int size)
+{
+ return (gr_complex*)volk_malloc(sizeof(gr_complex) * size, volk_get_alignment());
+}
+
+float* malloc_float(int size)
+{
+ return (float*)volk_malloc(sizeof(float) * size, volk_get_alignment());
+}
+
+double* malloc_double(int size)
+{
+ return (double*)volk_malloc(sizeof(double) * size, volk_get_alignment());
+}
+
+void free(void* b) { volk_free(b); }
+
+boost::mutex& planner::mutex()
+{
+ static boost::mutex s_planning_mutex;
+
+ return s_planning_mutex;
+}
+
+static std::string wisdom_filename()
+{
+ static fs::path path;
+ path = fs::path(gr::appdata_path()) / ".gr_fftw_wisdom";
+ return path.string();
+}
+
+static void wisdom_lock_init()
+{
+ if (wisdom_lock_init_done)
+ return;
- double *
- malloc_double(int size)
- {
- return (double*) volk_malloc (sizeof (double)*size, volk_get_alignment ());
+ const std::string wisdom_lock_file = wisdom_filename() + ".lock";
+ // std::cerr << "Creating FFTW wisdom lockfile: " << wisdom_lock_file << std::endl;
+ int fd =
+ open(wisdom_lock_file.c_str(), O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK, 0666);
+ if (fd < 0) {
+ throw std::runtime_error("Failed to create FFTW wisdom lockfile: " +
+ wisdom_lock_file);
}
-
- void
- free(void *b)
- {
- volk_free(b);
+ close(fd);
+ wisdom_lock = boost::interprocess::file_lock(wisdom_lock_file.c_str());
+ wisdom_lock_init_done = true;
+}
+
+static void lock_wisdom()
+{
+ wisdom_thread_mutex.lock();
+ wisdom_lock_init();
+ wisdom_lock.lock();
+}
+
+static void unlock_wisdom()
+{
+ // Assumes 'lock_wisdom' has already been called (i.e. this file_lock is valid)
+ wisdom_lock.unlock();
+ wisdom_thread_mutex.unlock();
+}
+
+static void import_wisdom()
+{
+ const std::string filename = wisdom_filename();
+ FILE* fp = fopen(filename.c_str(), "r");
+ if (fp != 0) {
+ int r = fftwf_import_wisdom_from_file(fp);
+ fclose(fp);
+ if (!r) {
+ fprintf(stderr, "gr::fft: can't import wisdom from %s\n", filename.c_str());
+ }
}
+}
- boost::mutex &
- planner::mutex()
- {
- static boost::mutex s_planning_mutex;
+static void config_threading(int nthreads)
+{
+ static int fftw_threads_inited = 0;
- return s_planning_mutex;
+#ifdef FFTW3F_THREADS
+ if (fftw_threads_inited == 0) {
+ fftw_threads_inited = 1;
+ fftwf_init_threads();
}
- static std::string
- wisdom_filename()
- {
- static fs::path path;
- path = fs::path(gr::appdata_path()) / ".gr_fftw_wisdom";
- return path.string();
+ fftwf_plan_with_nthreads(nthreads);
+#endif
+}
+
+static void export_wisdom()
+{
+ const std::string filename = wisdom_filename();
+ FILE* fp = fopen(filename.c_str(), "w");
+ if (fp != 0) {
+ fftwf_export_wisdom_to_file(fp);
+ fclose(fp);
+ } else {
+ fprintf(stderr, "fft_impl_fftw: ");
+ perror(filename.c_str());
}
+}
- static void
- wisdom_lock_init()
- {
- if (wisdom_lock_init_done)
- return;
+// ----------------------------------------------------------------
- const std::string wisdom_lock_file = wisdom_filename() + ".lock";
- // std::cerr << "Creating FFTW wisdom lockfile: " << wisdom_lock_file << std::endl;
- int fd = open(wisdom_lock_file.c_str(),
- O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK,
- 0666);
- if (fd < 0) {
- throw std::runtime_error("Failed to create FFTW wisdom lockfile: " + wisdom_lock_file);
- }
- close(fd);
- wisdom_lock = boost::interprocess::file_lock(wisdom_lock_file.c_str());
- wisdom_lock_init_done = true;
- }
+fft_complex::fft_complex(int fft_size, bool forward, int nthreads)
+{
+ // Hold global mutex during plan construction and destruction.
+ planner::scoped_lock lock(planner::mutex());
- static void
- lock_wisdom()
- {
- wisdom_thread_mutex.lock();
- wisdom_lock_init();
- wisdom_lock.lock();
- }
+ assert(sizeof(fftwf_complex) == sizeof(gr_complex));
- static void
- unlock_wisdom()
- {
- // Assumes 'lock_wisdom' has already been called (i.e. this file_lock is valid)
- wisdom_lock.unlock();
- wisdom_thread_mutex.unlock();
+ if (fft_size <= 0) {
+ throw std::out_of_range("fft_impl_fftw: invalid fft_size");
}
- static void
- import_wisdom()
- {
- const std::string filename = wisdom_filename ();
- FILE *fp = fopen (filename.c_str(), "r");
- if (fp != 0){
- int r = fftwf_import_wisdom_from_file (fp);
- fclose (fp);
- if (!r){
- fprintf (stderr, "gr::fft: can't import wisdom from %s\n", filename.c_str());
- }
- }
+ d_fft_size = fft_size;
+ d_inbuf = (gr_complex*)volk_malloc(sizeof(gr_complex) * inbuf_length(),
+ volk_get_alignment());
+ if (d_inbuf == 0) {
+ throw std::runtime_error("volk_malloc");
}
-
- static void
- config_threading(int nthreads)
- {
- static int fftw_threads_inited = 0;
-
-#ifdef FFTW3F_THREADS
- if (fftw_threads_inited == 0)
- {
- fftw_threads_inited = 1;
- fftwf_init_threads();
+ d_outbuf = (gr_complex*)volk_malloc(sizeof(gr_complex) * outbuf_length(),
+ volk_get_alignment());
+ if (d_outbuf == 0) {
+ volk_free(d_inbuf);
+ throw std::runtime_error("volk_malloc");
}
- fftwf_plan_with_nthreads(nthreads);
-#endif
- }
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ lock_wisdom();
+ import_wisdom(); // load prior wisdom from disk
- static void
- export_wisdom()
- {
- const std::string filename = wisdom_filename ();
- FILE *fp = fopen (filename.c_str(), "w");
- if (fp != 0){
- fftwf_export_wisdom_to_file (fp);
- fclose (fp);
- }
- else {
- fprintf (stderr, "fft_impl_fftw: ");
- perror (filename.c_str());
- }
- }
-
-// ----------------------------------------------------------------
+ d_plan = fftwf_plan_dft_1d(fft_size,
+ reinterpret_cast<fftwf_complex*>(d_inbuf),
+ reinterpret_cast<fftwf_complex*>(d_outbuf),
+ forward ? FFTW_FORWARD : FFTW_BACKWARD,
+ FFTW_MEASURE);
- fft_complex::fft_complex(int fft_size, bool forward, int nthreads)
- {
- // Hold global mutex during plan construction and destruction.
- planner::scoped_lock lock(planner::mutex());
-
- assert (sizeof (fftwf_complex) == sizeof (gr_complex));
-
- if (fft_size <= 0){
- throw std::out_of_range ("fft_impl_fftw: invalid fft_size");
- }
-
- d_fft_size = fft_size;
- d_inbuf = (gr_complex *) volk_malloc (sizeof (gr_complex) * inbuf_length (), volk_get_alignment ());
- if (d_inbuf == 0) {
- throw std::runtime_error ("volk_malloc");
- }
- d_outbuf = (gr_complex *) volk_malloc (sizeof (gr_complex) * outbuf_length (), volk_get_alignment ());
- if (d_outbuf == 0) {
- volk_free (d_inbuf);
- throw std::runtime_error ("volk_malloc");
- }
-
- d_nthreads = nthreads;
- config_threading(nthreads);
- lock_wisdom();
- import_wisdom(); // load prior wisdom from disk
-
- d_plan = fftwf_plan_dft_1d (fft_size,
- reinterpret_cast<fftwf_complex *>(d_inbuf),
- reinterpret_cast<fftwf_complex *>(d_outbuf),
- forward ? FFTW_FORWARD : FFTW_BACKWARD,
- FFTW_MEASURE);
-
- if (d_plan == NULL) {
+ if (d_plan == NULL) {
fprintf(stderr, "gr::fft: error creating plan\n");
- throw std::runtime_error ("fftwf_plan_dft_1d failed");
- }
- export_wisdom(); // store new wisdom to disk
- unlock_wisdom();
+ throw std::runtime_error("fftwf_plan_dft_1d failed");
}
-
- fft_complex::~fft_complex()
- {
- // Hold global mutex during plan construction and destruction.
- planner::scoped_lock lock(planner::mutex());
-
- fftwf_destroy_plan ((fftwf_plan) d_plan);
- volk_free (d_inbuf);
- volk_free (d_outbuf);
+ export_wisdom(); // store new wisdom to disk
+ unlock_wisdom();
+}
+
+fft_complex::~fft_complex()
+{
+ // Hold global mutex during plan construction and destruction.
+ planner::scoped_lock lock(planner::mutex());
+
+ fftwf_destroy_plan((fftwf_plan)d_plan);
+ volk_free(d_inbuf);
+ volk_free(d_outbuf);
+}
+
+void fft_complex::set_nthreads(int n)
+{
+ if (n <= 0) {
+ throw std::out_of_range("gr::fft: invalid number of threads");
}
-
- void
- fft_complex::set_nthreads(int n)
- {
- if (n <= 0) {
- throw std::out_of_range ("gr::fft: invalid number of threads");
- }
- d_nthreads = n;
+ d_nthreads = n;
#ifdef FFTW3F_THREADS
- fftwf_plan_with_nthreads(d_nthreads);
+ fftwf_plan_with_nthreads(d_nthreads);
#endif
- }
+}
- void
- fft_complex::execute()
- {
- fftwf_execute((fftwf_plan) d_plan);
- }
+void fft_complex::execute() { fftwf_execute((fftwf_plan)d_plan); }
// ----------------------------------------------------------------
- fft_real_fwd::fft_real_fwd (int fft_size, int nthreads)
- {
- // Hold global mutex during plan construction and destruction.
- planner::scoped_lock lock(planner::mutex());
+fft_real_fwd::fft_real_fwd(int fft_size, int nthreads)
+{
+ // Hold global mutex during plan construction and destruction.
+ planner::scoped_lock lock(planner::mutex());
- assert (sizeof (fftwf_complex) == sizeof (gr_complex));
+ assert(sizeof(fftwf_complex) == sizeof(gr_complex));
- if (fft_size <= 0) {
- throw std::out_of_range ("gr::fft: invalid fft_size");
- }
+ if (fft_size <= 0) {
+ throw std::out_of_range("gr::fft: invalid fft_size");
+ }
- d_fft_size = fft_size;
- d_inbuf = (float *) volk_malloc (sizeof (float) * inbuf_length (), volk_get_alignment ());
- if (d_inbuf == 0) {
- throw std::runtime_error ("volk_malloc");
- }
+ d_fft_size = fft_size;
+ d_inbuf = (float*)volk_malloc(sizeof(float) * inbuf_length(), volk_get_alignment());
+ if (d_inbuf == 0) {
+ throw std::runtime_error("volk_malloc");
+ }
- d_outbuf = (gr_complex *) volk_malloc (sizeof (gr_complex) * outbuf_length (), volk_get_alignment ());
- if (d_outbuf == 0) {
- volk_free (d_inbuf);
- throw std::runtime_error ("volk_malloc");
- }
+ d_outbuf = (gr_complex*)volk_malloc(sizeof(gr_complex) * outbuf_length(),
+ volk_get_alignment());
+ if (d_outbuf == 0) {
+ volk_free(d_inbuf);
+ throw std::runtime_error("volk_malloc");
+ }
- d_nthreads = nthreads;
- config_threading(nthreads);
- lock_wisdom();
- import_wisdom(); // load prior wisdom from disk
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ lock_wisdom();
+ import_wisdom(); // load prior wisdom from disk
- d_plan = fftwf_plan_dft_r2c_1d (fft_size,
- d_inbuf,
- reinterpret_cast<fftwf_complex *>(d_outbuf),
- FFTW_MEASURE);
+ d_plan = fftwf_plan_dft_r2c_1d(
+ fft_size, d_inbuf, reinterpret_cast<fftwf_complex*>(d_outbuf), FFTW_MEASURE);
- if (d_plan == NULL) {
+ if (d_plan == NULL) {
fprintf(stderr, "gr::fft::fft_real_fwd: error creating plan\n");
- throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed");
- }
- export_wisdom(); // store new wisdom to disk
- unlock_wisdom();
+ throw std::runtime_error("fftwf_plan_dft_r2c_1d failed");
}
-
- 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);
- volk_free (d_inbuf);
- volk_free (d_outbuf);
+ 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);
+ volk_free(d_inbuf);
+ volk_free(d_outbuf);
+}
+
+void fft_real_fwd::set_nthreads(int n)
+{
+ if (n <= 0) {
+ throw std::out_of_range(
+ "gr::fft::fft_real_fwd::set_nthreads: invalid number of threads");
}
-
- void
- fft_real_fwd::set_nthreads(int n)
- {
- if (n <= 0) {
- throw std::out_of_range ("gr::fft::fft_real_fwd::set_nthreads: invalid number of threads");
- }
- d_nthreads = n;
+ d_nthreads = n;
#ifdef FFTW3F_THREADS
- fftwf_plan_with_nthreads(d_nthreads);
+ 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)
+{
+ // Hold global mutex during plan construction and destruction.
+ planner::scoped_lock lock(planner::mutex());
+
+ assert(sizeof(fftwf_complex) == sizeof(gr_complex));
+
+ if (fft_size <= 0) {
+ throw std::out_of_range("gr::fft::fft_real_rev: invalid fft_size");
}
- void
- fft_real_fwd::execute()
- {
- fftwf_execute ((fftwf_plan) d_plan);
+ d_fft_size = fft_size;
+ d_inbuf = (gr_complex*)volk_malloc(sizeof(gr_complex) * inbuf_length(),
+ volk_get_alignment());
+ if (d_inbuf == 0) {
+ throw std::runtime_error("volk_malloc");
}
- // ----------------------------------------------------------------
-
- fft_real_rev::fft_real_rev(int fft_size, int nthreads)
- {
- // Hold global mutex during plan construction and destruction.
- planner::scoped_lock lock(planner::mutex());
-
- assert (sizeof (fftwf_complex) == sizeof (gr_complex));
-
- if (fft_size <= 0) {
- throw std::out_of_range ("gr::fft::fft_real_rev: invalid fft_size");
- }
-
- d_fft_size = fft_size;
- d_inbuf = (gr_complex *) volk_malloc (sizeof (gr_complex) * inbuf_length (), volk_get_alignment ());
- if (d_inbuf == 0) {
- throw std::runtime_error ("volk_malloc");
- }
-
- d_outbuf = (float *) volk_malloc (sizeof (float) * outbuf_length (), volk_get_alignment ());
- if (d_outbuf == 0) {
- volk_free (d_inbuf);
- throw std::runtime_error ("volk_malloc");
- }
-
- d_nthreads = nthreads;
- 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),
- d_outbuf,
- FFTW_MEASURE);
-
- if (d_plan == NULL) {
- fprintf(stderr, "gr::fft::fft_real_rev: error creating plan\n");
- throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed");
- }
- export_wisdom (); // store new wisdom to disk
- unlock_wisdom();
+ d_outbuf = (float*)volk_malloc(sizeof(float) * outbuf_length(), volk_get_alignment());
+ if (d_outbuf == 0) {
+ volk_free(d_inbuf);
+ throw std::runtime_error("volk_malloc");
}
- fft_real_rev::~fft_real_rev ()
- {
- // Hold global mutex during plan construction and destruction.
- planner::scoped_lock lock(planner::mutex());
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ lock_wisdom();
+ import_wisdom(); // load prior wisdom from disk
- fftwf_destroy_plan ((fftwf_plan) d_plan);
- volk_free (d_inbuf);
- volk_free (d_outbuf);
- }
+ // 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), d_outbuf, FFTW_MEASURE);
- void
- fft_real_rev::set_nthreads(int n)
- {
- if (n <= 0) {
- throw std::out_of_range ("gr::fft::fft_real_rev::set_nthreads: invalid number of threads");
- }
- d_nthreads = n;
+ if (d_plan == NULL) {
+ fprintf(stderr, "gr::fft::fft_real_rev: error creating plan\n");
+ 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()
+{
+ // Hold global mutex during plan construction and destruction.
+ planner::scoped_lock lock(planner::mutex());
+
+ fftwf_destroy_plan((fftwf_plan)d_plan);
+ volk_free(d_inbuf);
+ volk_free(d_outbuf);
+}
+
+void fft_real_rev::set_nthreads(int n)
+{
+ if (n <= 0) {
+ throw std::out_of_range(
+ "gr::fft::fft_real_rev::set_nthreads: invalid number of threads");
+ }
+ d_nthreads = n;
#ifdef FFTW3F_THREADS
- fftwf_plan_with_nthreads(d_nthreads);
+ fftwf_plan_with_nthreads(d_nthreads);
#endif
- }
+}
- void
- fft_real_rev::execute ()
- {
- fftwf_execute ((fftwf_plan) d_plan);
- }
+void fft_real_rev::execute() { fftwf_execute((fftwf_plan)d_plan); }
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
diff --git a/gr-fft/lib/fft_vcc_fftw.cc b/gr-fft/lib/fft_vcc_fftw.cc
index 3b23058df5..9c546a92d7 100644
--- a/gr-fft/lib/fft_vcc_fftw.cc
+++ b/gr-fft/lib/fft_vcc_fftw.cc
@@ -30,117 +30,111 @@
#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::get_initial_sptr(new 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_shift(shift)
- {
- d_fft = new fft_complex(d_fft_size, forward, nthreads);
- if(!set_window(window))
+namespace fft {
+
+fft_vcc::sptr fft_vcc::make(int fft_size,
+ bool forward,
+ const std::vector<float>& window,
+ bool shift,
+ int nthreads)
+{
+ return gnuradio::get_initial_sptr(
+ new 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_shift(shift)
+{
+ d_fft = new fft_complex(d_fft_size, forward, nthreads);
+ if (!set_window(window))
throw std::runtime_error("fft_vcc: window not the same length as fft_size\n");
- }
-
- fft_vcc_fftw::~fft_vcc_fftw()
- {
- delete d_fft;
- }
-
- void
- fft_vcc_fftw::set_nthreads(int n)
- {
- d_fft->set_nthreads(n);
- }
+}
+
+fft_vcc_fftw::~fft_vcc_fftw() { delete d_fft; }
+
+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.size() == 0 || 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.size()) {
+ gr_complex* dst = d_fft->get_inbuf();
+ if (!d_forward && d_shift) {
+ unsigned int offset = (!d_forward && d_shift) ? (d_fft_size / 2) : 0;
+ 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);
+ }
+ }
- int
- fft_vcc_fftw::nthreads() const
- {
- return d_fft->nthreads();
- }
+ // 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);
+ }
- bool
- fft_vcc_fftw::set_window(const std::vector<float> &window)
- {
- if(window.size()==0 || window.size()==d_fft_size) {
- d_window=window;
- return true;
- }
- else
- return false;
+ in += d_fft_size;
+ out += d_fft_size;
}
- 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.size()) {
- gr_complex *dst = d_fft->get_inbuf();
- if(!d_forward && d_shift) {
- unsigned int offset = (!d_forward && d_shift)?(d_fft_size/2):0;
- 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;
- }
+ return noutput_items;
+}
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
diff --git a/gr-fft/lib/fft_vcc_fftw.h b/gr-fft/lib/fft_vcc_fftw.h
index 375bb62a35..45afdd024f 100644
--- a/gr-fft/lib/fft_vcc_fftw.h
+++ b/gr-fft/lib/fft_vcc_fftw.h
@@ -27,34 +27,36 @@
#include <gnuradio/fft/fft.h>
namespace gr {
- namespace fft {
-
- class FFT_API fft_vcc_fftw : public fft_vcc
- {
- private:
- fft_complex *d_fft;
- unsigned int d_fft_size;
- std::vector<float> d_window;
- bool d_forward;
- bool d_shift;
-
- public:
- fft_vcc_fftw(int fft_size, bool forward,
- const std::vector<float> &window,
- bool shift, int nthreads=1);
-
- ~fft_vcc_fftw();
-
- void set_nthreads(int n);
- int nthreads() const;
- bool set_window(const std::vector<float> &window);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace fft */
+namespace fft {
+
+class FFT_API fft_vcc_fftw : public fft_vcc
+{
+private:
+ fft_complex* d_fft;
+ unsigned int d_fft_size;
+ std::vector<float> d_window;
+ bool d_forward;
+ bool d_shift;
+
+public:
+ fft_vcc_fftw(int fft_size,
+ bool forward,
+ const std::vector<float>& window,
+ bool shift,
+ int nthreads = 1);
+
+ ~fft_vcc_fftw();
+
+ void set_nthreads(int n);
+ int nthreads() const;
+ bool set_window(const std::vector<float>& window);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H */
diff --git a/gr-fft/lib/fft_vfc_fftw.cc b/gr-fft/lib/fft_vfc_fftw.cc
index b635c3b9bd..eac4268ba5 100644
--- a/gr-fft/lib/fft_vfc_fftw.cc
+++ b/gr-fft/lib/fft_vfc_fftw.cc
@@ -30,97 +30,81 @@
#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::get_initial_sptr(new 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_forward(forward)
- {
- d_fft = new fft_complex(d_fft_size, d_forward, nthreads);
- if(!set_window(window))
+namespace fft {
+
+fft_vfc::sptr
+fft_vfc::make(int fft_size, bool forward, const std::vector<float>& window, int nthreads)
+{
+ return gnuradio::get_initial_sptr(
+ new 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_forward(forward)
+{
+ d_fft = new fft_complex(d_fft_size, d_forward, nthreads);
+ if (!set_window(window))
throw std::runtime_error("fft_vfc: window not the same length as fft_size\n");
- }
-
- fft_vfc_fftw::~fft_vfc_fftw()
- {
- delete d_fft;
- }
+}
- void
- fft_vfc_fftw::set_nthreads(int n)
- {
- d_fft->set_nthreads(n);
- }
+fft_vfc_fftw::~fft_vfc_fftw() { delete d_fft; }
- int
- fft_vfc_fftw::nthreads() const
- {
- return d_fft->nthreads();
- }
+void fft_vfc_fftw::set_nthreads(int n) { d_fft->set_nthreads(n); }
- bool
- fft_vfc_fftw::set_window(const std::vector<float> &window)
- {
- if(window.size()==0 || window.size()==d_fft_size) {
- d_window=window;
- return true;
- }
- else
- return false;
- }
+int fft_vfc_fftw::nthreads() const { return d_fft->nthreads(); }
- 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];
+bool fft_vfc_fftw::set_window(const std::vector<float>& window)
+{
+ if (window.size() == 0 || window.size() == d_fft_size) {
+ d_window = window;
+ return true;
+ } else
+ return false;
+}
- unsigned int output_data_size = output_signature()->sizeof_stream_item (0);
+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];
- int count = 0;
+ unsigned int output_data_size = output_signature()->sizeof_stream_item(0);
- while(count++ < noutput_items) {
+ int count = 0;
- // copy input into optimally aligned buffer
- if(d_window.size()) {
- 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];
- }
+ while (count++ < noutput_items) {
- // compute the fft
- d_fft->execute();
+ // copy input into optimally aligned buffer
+ if (d_window.size()) {
+ 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];
+ }
- // copy result to output stream
- memcpy(out, d_fft->get_outbuf(), output_data_size);
+ // compute the fft
+ d_fft->execute();
- in += d_fft_size;
- out += d_fft_size;
- }
+ // copy result to output stream
+ memcpy(out, d_fft->get_outbuf(), output_data_size);
- return noutput_items;
+ in += d_fft_size;
+ out += d_fft_size;
}
- } /* namespace fft */
-} /* namespace gr */
+ 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
index f500129e2e..4b0e905643 100644
--- a/gr-fft/lib/fft_vfc_fftw.h
+++ b/gr-fft/lib/fft_vfc_fftw.h
@@ -27,33 +27,34 @@
#include <gnuradio/fft/fft.h>
namespace gr {
- namespace fft {
-
- class FFT_API fft_vfc_fftw : public fft_vfc
- {
- private:
- fft_complex *d_fft;
- unsigned int d_fft_size;
- std::vector<float> d_window;
- bool d_forward;
-
- public:
- fft_vfc_fftw(int fft_size, bool forward,
- const std::vector<float> &window,
- int nthreads=1);
-
- ~fft_vfc_fftw();
-
- void set_nthreads(int n);
- int nthreads() const;
- bool set_window(const std::vector<float> &window);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace fft */
+namespace fft {
+
+class FFT_API fft_vfc_fftw : public fft_vfc
+{
+private:
+ fft_complex* d_fft;
+ unsigned int d_fft_size;
+ std::vector<float> d_window;
+ bool d_forward;
+
+public:
+ fft_vfc_fftw(int fft_size,
+ bool forward,
+ const std::vector<float>& window,
+ int nthreads = 1);
+
+ ~fft_vfc_fftw();
+
+ void set_nthreads(int n);
+ int nthreads() const;
+ bool set_window(const std::vector<float>& window);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H */
diff --git a/gr-fft/lib/goertzel.cc b/gr-fft/lib/goertzel.cc
index 324d2a76a2..96b41b0126 100644
--- a/gr-fft/lib/goertzel.cc
+++ b/gr-fft/lib/goertzel.cc
@@ -29,57 +29,49 @@
#include <cmath>
namespace gr {
- namespace fft {
+namespace fft {
- goertzel::goertzel(int rate, int len, float freq)
- {
- set_params(rate, len, freq);
- }
+goertzel::goertzel(int rate, int len, float freq) { set_params(rate, len, freq); }
- void
- goertzel::set_params(int rate, int len, float freq)
- {
- d_d1 = 0.0;
- d_d2 = 0.0;
+void goertzel::set_params(int rate, int len, float freq)
+{
+ d_d1 = 0.0;
+ d_d2 = 0.0;
- float w = 2.0*GR_M_PI*freq/rate;
- d_wr = 2.0*std::cos(w);
- d_wi = std::sin(w);
- d_len = len;
- d_processed = 0;
- }
+ float w = 2.0 * GR_M_PI * freq / rate;
+ d_wr = 2.0 * std::cos(w);
+ d_wi = std::sin(w);
+ d_len = len;
+ d_processed = 0;
+}
- gr_complex
- goertzel::batch(float *in)
- {
- d_d1 = 0.0;
- d_d2 = 0.0;
+gr_complex goertzel::batch(float* in)
+{
+ d_d1 = 0.0;
+ d_d2 = 0.0;
- for(int i = 0; i < d_len; i++)
- input(in[i]);
+ for (int i = 0; i < d_len; i++)
+ input(in[i]);
- return output();
- }
+ return output();
+}
- void
- goertzel::input(const float &input)
- {
- float y = input + d_wr*d_d1 - d_d2;
- d_d2 = d_d1;
- d_d1 = y;
- d_processed++;
- }
+void goertzel::input(const float& input)
+{
+ float y = input + d_wr * d_d1 - d_d2;
+ d_d2 = d_d1;
+ d_d1 = y;
+ d_processed++;
+}
- gr_complex
- goertzel::output()
- {
- gr_complex out((0.5*d_wr*d_d1-d_d2)/d_len, (d_wi*d_d1)/d_len);
- d_d1 = 0.0;
- d_d2 = 0.0;
- d_processed = 0;
- return out;
- }
-
- } /* namespace fft */
-}/* namespace gr */
+gr_complex goertzel::output()
+{
+ gr_complex out((0.5 * d_wr * d_d1 - d_d2) / d_len, (d_wi * d_d1) / d_len);
+ d_d1 = 0.0;
+ d_d2 = 0.0;
+ d_processed = 0;
+ return out;
+}
+} /* namespace fft */
+} /* namespace gr */
diff --git a/gr-fft/lib/goertzel_fc_impl.cc b/gr-fft/lib/goertzel_fc_impl.cc
index ba26df0ca3..a8f9d58b5a 100644
--- a/gr-fft/lib/goertzel_fc_impl.cc
+++ b/gr-fft/lib/goertzel_fc_impl.cc
@@ -28,58 +28,53 @@
#include <gnuradio/io_signature.h>
namespace gr {
- namespace fft {
+namespace fft {
- goertzel_fc::sptr goertzel_fc::make(int rate, int len, float freq)
- {
- return gnuradio::get_initial_sptr(new goertzel_fc_impl(rate, len, freq));
- }
+goertzel_fc::sptr goertzel_fc::make(int rate, int len, float freq)
+{
+ return gnuradio::get_initial_sptr(new goertzel_fc_impl(rate, len, freq));
+}
- goertzel_fc_impl::goertzel_fc_impl(int rate, int len, float freq)
- : sync_decimator("goertzel_fc",
- io_signature::make (1, 1, sizeof(float)),
- io_signature::make (1, 1, sizeof(gr_complex)),
- len),
- d_goertzel(rate, len, freq)
- {
- d_len = len;
- d_rate = rate;
- d_freq = freq;
- }
+goertzel_fc_impl::goertzel_fc_impl(int rate, int len, float freq)
+ : sync_decimator("goertzel_fc",
+ io_signature::make(1, 1, sizeof(float)),
+ io_signature::make(1, 1, sizeof(gr_complex)),
+ len),
+ d_goertzel(rate, len, freq)
+{
+ d_len = len;
+ d_rate = rate;
+ d_freq = freq;
+}
- goertzel_fc_impl::~goertzel_fc_impl()
- {
- }
+goertzel_fc_impl::~goertzel_fc_impl() {}
- void
- goertzel_fc_impl::set_freq(float freq)
- {
- d_freq = freq;
- d_goertzel.set_params(d_rate, d_len, d_freq);
- }
+void goertzel_fc_impl::set_freq(float freq)
+{
+ d_freq = freq;
+ d_goertzel.set_params(d_rate, d_len, d_freq);
+}
- void
- goertzel_fc_impl::set_rate(int rate)
- {
- d_rate = rate;
- d_goertzel.set_params(d_rate, d_len, d_freq);
- }
-
- int
- goertzel_fc_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- float *in = (float *)input_items[0];
- gr_complex *out = (gr_complex *)output_items[0];
+void goertzel_fc_impl::set_rate(int rate)
+{
+ d_rate = rate;
+ d_goertzel.set_params(d_rate, d_len, d_freq);
+}
- for(int i = 0; i < noutput_items; i++) {
- *out++ = d_goertzel.batch(in);
- in += d_len;
- }
+int goertzel_fc_impl::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ float* in = (float*)input_items[0];
+ gr_complex* out = (gr_complex*)output_items[0];
- return noutput_items;
+ for (int i = 0; i < noutput_items; i++) {
+ *out++ = d_goertzel.batch(in);
+ in += d_len;
}
- } /* namespace fft */
+ return noutput_items;
+}
+
+} /* namespace fft */
} /* namespace gr */
diff --git a/gr-fft/lib/goertzel_fc_impl.h b/gr-fft/lib/goertzel_fc_impl.h
index e007bcfb73..607e7e1f95 100644
--- a/gr-fft/lib/goertzel_fc_impl.h
+++ b/gr-fft/lib/goertzel_fc_impl.h
@@ -27,34 +27,33 @@
#include <gnuradio/fft/goertzel.h>
namespace gr {
- namespace fft {
+namespace fft {
- class FFT_API goertzel_fc_impl : public goertzel_fc
- {
- private:
- goertzel d_goertzel;
- int d_len;
- float d_freq;
- int d_rate;
+class FFT_API goertzel_fc_impl : public goertzel_fc
+{
+private:
+ goertzel d_goertzel;
+ int d_len;
+ float d_freq;
+ int d_rate;
- public:
- goertzel_fc_impl(int rate, int len, float freq);
+public:
+ goertzel_fc_impl(int rate, int len, float freq);
- ~goertzel_fc_impl();
+ ~goertzel_fc_impl();
- void set_freq(float freq);
- void set_rate(int rate);
+ void set_freq(float freq);
+ void set_rate(int rate);
- float freq() { return d_freq; }
- int rate() { return d_rate; }
+ float freq() { return d_freq; }
+ int rate() { return d_rate; }
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */
#endif /* INCLUDED_FFT_GOERTZEL_FC_IMPL_H */
-
diff --git a/gr-fft/lib/qa_fft_shift.cc b/gr-fft/lib/qa_fft_shift.cc
index e924af8629..fb587ec1dc 100644
--- a/gr-fft/lib/qa_fft_shift.cc
+++ b/gr-fft/lib/qa_fft_shift.cc
@@ -33,29 +33,29 @@ namespace fft {
BOOST_AUTO_TEST_CASE(t1)
{
- fft::fft_shift<int> s(1023);
+ fft::fft_shift<int> s(1023);
- std::vector<int> x_even{ 0, 1, 2, 3, -4, -3, -2, -1 };
- std::vector<int> y_even{ -4, -3, -2, -1, 0, 1, 2, 3 }; // expected result
+ std::vector<int> x_even{ 0, 1, 2, 3, -4, -3, -2, -1 };
+ std::vector<int> y_even{ -4, -3, -2, -1, 0, 1, 2, 3 }; // expected result
- s.shift(x_even);
- BOOST_TEST(x_even == y_even, boost::test_tools::per_element());
+ s.shift(x_even);
+ BOOST_TEST(x_even == y_even, boost::test_tools::per_element());
- // two shifts should not change the result
- s.shift(x_even);
- s.shift(x_even);
- BOOST_TEST(x_even == y_even, boost::test_tools::per_element());
+ // two shifts should not change the result
+ s.shift(x_even);
+ s.shift(x_even);
+ BOOST_TEST(x_even == y_even, boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(t2)
{
- fft::fft_shift<int> s(7);
+ fft::fft_shift<int> s(7);
- std::vector<int> x_odd{ 0, 1, 2, 3, -3, -2, -1 };
- std::vector<int> y_odd{ -3, -2, -1, 0, 1, 2, 3 }; // expected result
+ std::vector<int> x_odd{ 0, 1, 2, 3, -3, -2, -1 };
+ std::vector<int> y_odd{ -3, -2, -1, 0, 1, 2, 3 }; // expected result
- s.shift(x_odd);
- BOOST_TEST(x_odd == y_odd, boost::test_tools::per_element());
+ s.shift(x_odd);
+ BOOST_TEST(x_odd == y_odd, boost::test_tools::per_element());
}
} /* namespace fft */
diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc
index 0c1e27f66a..9a1f4600b5 100644
--- a/gr-fft/lib/window.cc
+++ b/gr-fft/lib/window.cc
@@ -29,352 +29,328 @@
#include <stdexcept>
namespace gr {
- namespace fft {
+namespace fft {
-#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
+#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
- static double Izero(double x)
- {
- double sum, u, halfx, temp;
- int n;
+static double Izero(double x)
+{
+ double sum, u, halfx, temp;
+ int n;
- sum = u = n = 1;
- halfx = x/2.0;
- do {
- temp = halfx/(double)n;
+ sum = u = n = 1;
+ halfx = x / 2.0;
+ do {
+ temp = halfx / (double)n;
n += 1;
temp *= temp;
u *= temp;
sum += u;
- } while (u >= IzeroEPSILON*sum);
- return(sum);
- }
-
- double midn(int ntaps)
- {
- return ntaps/2.0;
- }
-
- double midm1(int ntaps)
- {
- return (ntaps - 1.0)/2.0;
- }
-
- double midp1(int ntaps)
- {
- return (ntaps + 1.0)/2.0;
- }
-
- double freq(int ntaps)
- {
- return 2.0*GR_M_PI/ntaps;
- }
-
- double rate(int ntaps)
- {
- return 1.0/(ntaps >> 1);
- }
-
- double
- window::max_attenuation(win_type type, double beta)
- {
- switch(type) {
- case(WIN_HAMMING): return 53; break;
- case(WIN_HANN): return 44; break;
- case(WIN_BLACKMAN): return 74; break;
- case(WIN_RECTANGULAR): return 21; break;
- case(WIN_KAISER): return (beta/0.1102 + 8.7); break;
- case(WIN_BLACKMAN_hARRIS): return 92; break;
- case(WIN_BARTLETT): return 27; break;
- case(WIN_FLATTOP): return 93; break;
- default:
+ } while (u >= IzeroEPSILON * sum);
+ return (sum);
+}
+
+double midn(int ntaps) { return ntaps / 2.0; }
+
+double midm1(int ntaps) { return (ntaps - 1.0) / 2.0; }
+
+double midp1(int ntaps) { return (ntaps + 1.0) / 2.0; }
+
+double freq(int ntaps) { return 2.0 * GR_M_PI / ntaps; }
+
+double rate(int ntaps) { return 1.0 / (ntaps >> 1); }
+
+double window::max_attenuation(win_type type, double beta)
+{
+ switch (type) {
+ case (WIN_HAMMING):
+ return 53;
+ break;
+ case (WIN_HANN):
+ return 44;
+ break;
+ case (WIN_BLACKMAN):
+ return 74;
+ break;
+ case (WIN_RECTANGULAR):
+ return 21;
+ break;
+ case (WIN_KAISER):
+ return (beta / 0.1102 + 8.7);
+ break;
+ case (WIN_BLACKMAN_hARRIS):
+ return 92;
+ break;
+ case (WIN_BARTLETT):
+ return 27;
+ break;
+ case (WIN_FLATTOP):
+ return 93;
+ break;
+ default:
throw std::out_of_range("window::max_attenuation: unknown window type provided.");
- }
- }
-
- std::vector<float>
- window::coswindow(int ntaps, float c0, float c1, float c2)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
-
- for(int n = 0; n < ntaps; n++)
- taps[n] = c0 - c1*cosf((2.0f*GR_M_PI*n)/M) + c2*cosf((4.0f*GR_M_PI*n)/M);
- return taps;
- }
-
- std::vector<float>
- window::coswindow(int ntaps, float c0, float c1, float c2, float c3)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
-
- for(int n = 0; n < ntaps; n++)
- taps[n] = c0 - c1*cosf((2.0f*GR_M_PI*n)/M) + c2*cosf((4.0f*GR_M_PI*n)/M) \
- - c3*cosf((6.0f*GR_M_PI*n)/M);
- return taps;
}
-
- std::vector<float>
- window::coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
-
- for(int n = 0; n < ntaps; n++)
- taps[n] = c0 - c1*cosf((2.0f*GR_M_PI*n)/M) + c2*cosf((4.0f*GR_M_PI*n)/M) \
- - c3*cosf((6.0f*GR_M_PI*n)/M) + c4*cosf((8.0f*GR_M_PI*n)/M);
- return taps;
- }
-
- std::vector<float>
- window::rectangular(int ntaps)
- {
- std::vector<float> taps(ntaps);
- for(int n = 0; n < ntaps; n++)
+}
+
+std::vector<float> window::coswindow(int ntaps, float c0, float c1, float c2)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for (int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1 * cosf((2.0f * GR_M_PI * n) / M) +
+ c2 * cosf((4.0f * GR_M_PI * n) / M);
+ return taps;
+}
+
+std::vector<float> window::coswindow(int ntaps, float c0, float c1, float c2, float c3)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for (int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1 * cosf((2.0f * GR_M_PI * n) / M) +
+ c2 * cosf((4.0f * GR_M_PI * n) / M) -
+ c3 * cosf((6.0f * GR_M_PI * n) / M);
+ return taps;
+}
+
+std::vector<float>
+window::coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for (int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1 * cosf((2.0f * GR_M_PI * n) / M) +
+ c2 * cosf((4.0f * GR_M_PI * n) / M) -
+ c3 * cosf((6.0f * GR_M_PI * n) / M) +
+ c4 * cosf((8.0f * GR_M_PI * n) / M);
+ return taps;
+}
+
+std::vector<float> window::rectangular(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ for (int n = 0; n < ntaps; n++)
taps[n] = 1;
- return taps;
- }
+ return taps;
+}
- std::vector<float>
- window::hamming(int ntaps)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
+std::vector<float> window::hamming(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
- for(int n = 0; n < ntaps; n++)
+ for (int n = 0; n < ntaps; n++)
taps[n] = 0.54 - 0.46 * cos((2 * GR_M_PI * n) / M);
- return taps;
- }
+ return taps;
+}
- std::vector<float>
- window::hann(int ntaps)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
+std::vector<float> window::hann(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
- for(int n = 0; n < ntaps; n++)
+ for (int n = 0; n < ntaps; n++)
taps[n] = 0.5 - 0.5 * cos((2 * GR_M_PI * n) / M);
- return taps;
- }
-
- std::vector<float>
- window::hanning(int ntaps)
- {
- return hann(ntaps);
- }
-
- std::vector<float>
- window::blackman(int ntaps)
- {
- return coswindow(ntaps, 0.42, 0.5, 0.08);
- }
-
- std::vector<float>
- window::blackman2(int ntaps)
- {
- return coswindow(ntaps, 0.34401, 0.49755, 0.15844);
- }
-
- std::vector<float>
- window::blackman3(int ntaps)
- {
- return coswindow(ntaps, 0.21747, 0.45325, 0.28256, 0.04672);
- }
-
- std::vector<float>
- window::blackman4(int ntaps)
- {
- return coswindow(ntaps, 0.084037, 0.29145, 0.375696, 0.20762, 0.041194);
- }
-
- std::vector<float>
- window::blackman_harris(int ntaps, int atten)
- {
- switch(atten) {
- case(61): return coswindow(ntaps, 0.42323, 0.49755, 0.07922);
- case(67): return coswindow(ntaps, 0.44959, 0.49364, 0.05677);
- case(74): return coswindow(ntaps, 0.40271, 0.49703, 0.09392, 0.00183);
- case(92): return coswindow(ntaps, 0.35875, 0.48829, 0.14128, 0.01168);
- default:
- throw std::out_of_range("window::blackman_harris: unknown attenuation value (must be 61, 67, 74, or 92)");
- }
- }
-
- std::vector<float>
- window::blackmanharris(int ntaps, int atten)
- {
- return blackman_harris(ntaps, atten);
- }
-
- std::vector<float>
- window::nuttal(int ntaps)
- {
- return nuttall(ntaps);
- }
-
- std::vector<float>
- window::nuttall(int ntaps)
- {
- return coswindow(ntaps, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
- }
-
- std::vector<float>
- window::blackman_nuttal(int ntaps)
- {
- return nuttall(ntaps);
- }
-
- std::vector<float>
- window::blackman_nuttall(int ntaps)
- {
- return nuttall(ntaps);
- }
-
- std::vector<float>
- window::nuttal_cfd(int ntaps)
- {
- return nuttall_cfd(ntaps);
- }
-
- std::vector<float>
- window::nuttall_cfd(int ntaps)
- {
- return coswindow(ntaps, 0.355768, 0.487396, 0.144232, 0.012604);
- }
-
- std::vector<float>
- window::flattop(int ntaps)
- {
- double scale = 4.63867;
- return coswindow(ntaps, 1.0/scale, 1.93/scale, 1.29/scale, 0.388/scale, 0.028/scale);
- }
-
- std::vector<float>
- window::kaiser(int ntaps, double beta)
- {
- if(beta < 0)
+ return taps;
+}
+
+std::vector<float> window::hanning(int ntaps) { return hann(ntaps); }
+
+std::vector<float> window::blackman(int ntaps)
+{
+ return coswindow(ntaps, 0.42, 0.5, 0.08);
+}
+
+std::vector<float> window::blackman2(int ntaps)
+{
+ return coswindow(ntaps, 0.34401, 0.49755, 0.15844);
+}
+
+std::vector<float> window::blackman3(int ntaps)
+{
+ return coswindow(ntaps, 0.21747, 0.45325, 0.28256, 0.04672);
+}
+
+std::vector<float> window::blackman4(int ntaps)
+{
+ return coswindow(ntaps, 0.084037, 0.29145, 0.375696, 0.20762, 0.041194);
+}
+
+std::vector<float> window::blackman_harris(int ntaps, int atten)
+{
+ switch (atten) {
+ case (61):
+ return coswindow(ntaps, 0.42323, 0.49755, 0.07922);
+ case (67):
+ return coswindow(ntaps, 0.44959, 0.49364, 0.05677);
+ case (74):
+ return coswindow(ntaps, 0.40271, 0.49703, 0.09392, 0.00183);
+ case (92):
+ return coswindow(ntaps, 0.35875, 0.48829, 0.14128, 0.01168);
+ default:
+ throw std::out_of_range("window::blackman_harris: unknown attenuation value "
+ "(must be 61, 67, 74, or 92)");
+ }
+}
+
+std::vector<float> window::blackmanharris(int ntaps, int atten)
+{
+ return blackman_harris(ntaps, atten);
+}
+
+std::vector<float> window::nuttal(int ntaps) { return nuttall(ntaps); }
+
+std::vector<float> window::nuttall(int ntaps)
+{
+ return coswindow(ntaps, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
+}
+
+std::vector<float> window::blackman_nuttal(int ntaps) { return nuttall(ntaps); }
+
+std::vector<float> window::blackman_nuttall(int ntaps) { return nuttall(ntaps); }
+
+std::vector<float> window::nuttal_cfd(int ntaps) { return nuttall_cfd(ntaps); }
+
+std::vector<float> window::nuttall_cfd(int ntaps)
+{
+ return coswindow(ntaps, 0.355768, 0.487396, 0.144232, 0.012604);
+}
+
+std::vector<float> window::flattop(int ntaps)
+{
+ double scale = 4.63867;
+ return coswindow(
+ ntaps, 1.0 / scale, 1.93 / scale, 1.29 / scale, 0.388 / scale, 0.028 / scale);
+}
+
+std::vector<float> window::kaiser(int ntaps, double beta)
+{
+ if (beta < 0)
throw std::out_of_range("window::kaiser: beta must be >= 0");
- std::vector<float> taps(ntaps);
-
- double IBeta = 1.0/Izero(beta);
- double inm1 = 1.0/((double)(ntaps-1));
- double temp;
-
- /* extracting first and last element out of the loop, since
- sqrt(1.0-temp*temp) might trigger unexpected floating point behaviour
- if |temp| = 1.0+epsilon, which can happen for i==0 and
- 1/i==1/(ntaps-1)==inm1 ; compare
- https://github.com/gnuradio/gnuradio/issues/1348 .
- In any case, the 0. Bessel function of first kind is 1 at point 0.
- */
- taps[0] = IBeta;
- for(int i = 1; i < ntaps-1; i++) {
- temp = 2*i*inm1 - 1;
- taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta;
- }
- taps[ntaps-1] = IBeta;
- return taps;
- }
-
- std::vector<float>
- window::bartlett(int ntaps)
- {
- std::vector<float> taps(ntaps);
- float M = static_cast<float>(ntaps - 1);
-
- for(int n = 0; n < ntaps/2; n++)
- taps[n] = 2*n/M;
- for(int n = ntaps/2; n < ntaps; n++)
- taps[n] = 2 - 2*n/M;
-
- return taps;
- }
-
- std::vector<float>
- window::welch(int ntaps)
- {
- std::vector<float> taps(ntaps);
- double m1 = midm1(ntaps);
- double p1 = midp1(ntaps);
- for(int i = 0; i < midn(ntaps)+1; i++) {
+ std::vector<float> taps(ntaps);
+
+ double IBeta = 1.0 / Izero(beta);
+ double inm1 = 1.0 / ((double)(ntaps - 1));
+ double temp;
+
+ /* extracting first and last element out of the loop, since
+ sqrt(1.0-temp*temp) might trigger unexpected floating point behaviour
+ if |temp| = 1.0+epsilon, which can happen for i==0 and
+ 1/i==1/(ntaps-1)==inm1 ; compare
+ https://github.com/gnuradio/gnuradio/issues/1348 .
+ In any case, the 0. Bessel function of first kind is 1 at point 0.
+ */
+ taps[0] = IBeta;
+ for (int i = 1; i < ntaps - 1; i++) {
+ temp = 2 * i * inm1 - 1;
+ taps[i] = Izero(beta * sqrt(1.0 - temp * temp)) * IBeta;
+ }
+ taps[ntaps - 1] = IBeta;
+ return taps;
+}
+
+std::vector<float> window::bartlett(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for (int n = 0; n < ntaps / 2; n++)
+ taps[n] = 2 * n / M;
+ for (int n = ntaps / 2; n < ntaps; n++)
+ taps[n] = 2 - 2 * n / M;
+
+ return taps;
+}
+
+std::vector<float> window::welch(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ double m1 = midm1(ntaps);
+ double p1 = midp1(ntaps);
+ for (int i = 0; i < midn(ntaps) + 1; i++) {
taps[i] = 1.0 - pow((i - m1) / p1, 2);
- taps[ntaps-i-1] = taps[i];
- }
- return taps;
- }
-
- std::vector<float>
- window::parzen(int ntaps)
- {
- std::vector<float> taps(ntaps);
- double m1 = midm1(ntaps);
- double m = midn(ntaps);
- int i;
- for(i = ntaps/4; i < 3*ntaps/4; i++) {
- taps[i] = 1.0 - 6.0*pow((i-m1)/m, 2.0) * (1.0 - fabs(i-m1)/m);
- }
- for(; i < ntaps; i++) {
- taps[i] = 2.0 * pow(1.0 - fabs(i-m1)/m, 3.0);
- taps[ntaps-i-1] = taps[i];
- }
- return taps;
- }
-
- std::vector<float>
- window::exponential(int ntaps, double d)
- {
- if(d < 0)
+ taps[ntaps - i - 1] = taps[i];
+ }
+ return taps;
+}
+
+std::vector<float> window::parzen(int ntaps)
+{
+ std::vector<float> taps(ntaps);
+ double m1 = midm1(ntaps);
+ double m = midn(ntaps);
+ int i;
+ for (i = ntaps / 4; i < 3 * ntaps / 4; i++) {
+ taps[i] = 1.0 - 6.0 * pow((i - m1) / m, 2.0) * (1.0 - fabs(i - m1) / m);
+ }
+ for (; i < ntaps; i++) {
+ taps[i] = 2.0 * pow(1.0 - fabs(i - m1) / m, 3.0);
+ taps[ntaps - i - 1] = taps[i];
+ }
+ return taps;
+}
+
+std::vector<float> window::exponential(int ntaps, double d)
+{
+ if (d < 0)
throw std::out_of_range("window::exponential: d must be >= 0");
- double m1 = midm1(ntaps);
- double p = 1.0 / (8.69*ntaps/(2.0*d));
- std::vector<float> taps(ntaps);
- for(int i = 0; i < midn(ntaps)+1; i++) {
- taps[i] = exp(-fabs(i - m1)*p);
- taps[ntaps-i-1] = taps[i];
- }
- return taps;
- }
-
- std::vector<float>
- window::riemann(int ntaps)
- {
- double cx;
- double sr1 = freq(ntaps);
- double mid = midn(ntaps);
- std::vector<float> taps(ntaps);
- for(int i = 0; i < mid; i++) {
- if(i == midn(ntaps)) {
- taps[i] = 1.0;
- taps[ntaps-i-1] = 1.0;
+ double m1 = midm1(ntaps);
+ double p = 1.0 / (8.69 * ntaps / (2.0 * d));
+ std::vector<float> taps(ntaps);
+ for (int i = 0; i < midn(ntaps) + 1; i++) {
+ taps[i] = exp(-fabs(i - m1) * p);
+ taps[ntaps - i - 1] = taps[i];
+ }
+ return taps;
+}
+
+std::vector<float> window::riemann(int ntaps)
+{
+ double cx;
+ double sr1 = freq(ntaps);
+ double mid = midn(ntaps);
+ std::vector<float> taps(ntaps);
+ for (int i = 0; i < mid; i++) {
+ if (i == midn(ntaps)) {
+ taps[i] = 1.0;
+ taps[ntaps - i - 1] = 1.0;
+ } else {
+ cx = sr1 * (i - mid);
+ taps[i] = sin(cx) / cx;
+ taps[ntaps - i - 1] = sin(cx) / cx;
}
- else {
- cx = sr1*(i - mid);
- taps[i] = sin(cx)/cx;
- taps[ntaps-i-1] = sin(cx)/cx;
- }
- }
- return taps;
}
-
- std::vector<float>
- window::build(win_type type, int ntaps, double beta)
- {
- switch (type) {
- case WIN_RECTANGULAR: return rectangular(ntaps);
- case WIN_HAMMING: return hamming(ntaps);
- case WIN_HANN: return hann(ntaps);
- case WIN_BLACKMAN: return blackman(ntaps);
- case WIN_BLACKMAN_hARRIS: return blackman_harris(ntaps);
- case WIN_KAISER: return kaiser(ntaps, beta);
- case WIN_BARTLETT: return bartlett(ntaps);
- case WIN_FLATTOP: return flattop(ntaps);
- default:
+ return taps;
+}
+
+std::vector<float> window::build(win_type type, int ntaps, double beta)
+{
+ switch (type) {
+ case WIN_RECTANGULAR:
+ return rectangular(ntaps);
+ case WIN_HAMMING:
+ return hamming(ntaps);
+ case WIN_HANN:
+ return hann(ntaps);
+ case WIN_BLACKMAN:
+ return blackman(ntaps);
+ case WIN_BLACKMAN_hARRIS:
+ return blackman_harris(ntaps);
+ case WIN_KAISER:
+ return kaiser(ntaps, beta);
+ case WIN_BARTLETT:
+ return bartlett(ntaps);
+ case WIN_FLATTOP:
+ return flattop(ntaps);
+ default:
throw std::out_of_range("window::build: type out of range");
- }
}
+}
- } /* namespace fft */
+} /* namespace fft */
} /* namespace gr */