summaryrefslogtreecommitdiff
path: root/gr-fft
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fft')
-rw-r--r--gr-fft/include/gnuradio/fft/fft_vcc.h33
-rw-r--r--gr-fft/include/gnuradio/fft/fft_vfc.h36
-rw-r--r--gr-fft/lib/fft.cc37
-rw-r--r--gr-fft/python/fft/CMakeLists.txt3
4 files changed, 92 insertions, 17 deletions
diff --git a/gr-fft/include/gnuradio/fft/fft_vcc.h b/gr-fft/include/gnuradio/fft/fft_vcc.h
index 1e09521b4f..28f6d1d0d4 100644
--- a/gr-fft/include/gnuradio/fft/fft_vcc.h
+++ b/gr-fft/include/gnuradio/fft/fft_vcc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc.
+ * Copyright 2004,2007,2008,2012,2018 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,6 +32,29 @@ namespace gr {
/*!
* \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
{
@@ -39,7 +62,13 @@ namespace gr {
// 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] shifted 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);
diff --git a/gr-fft/include/gnuradio/fft/fft_vfc.h b/gr-fft/include/gnuradio/fft/fft_vfc.h
index 91ed81fb17..5639465ab5 100644
--- a/gr-fft/include/gnuradio/fft/fft_vfc.h
+++ b/gr-fft/include/gnuradio/fft/fft_vfc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ * Copyright 2004,2010,2012,2018 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -30,16 +30,46 @@ namespace gr {
namespace fft {
/*!
- * \brief Compute forward or reverse FFT. float vector in / complex vector out.
+ * \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
+ 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] shifted 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,
int nthreads=1);
diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc
index 871ad9bcaa..718cd0990f 100644
--- a/gr-fft/lib/fft.cc
+++ b/gr-fft/lib/fft.cc
@@ -56,7 +56,8 @@ namespace fs = boost::filesystem;
namespace gr {
namespace fft {
static boost::mutex wisdom_thread_mutex;
- boost::interprocess::file_lock wisdom_lock;
+ 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)
@@ -99,15 +100,36 @@ namespace gr {
}
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;
+ }
+
+ static void
lock_wisdom()
{
- wisdom_thread_mutex.lock();
- wisdom_lock.lock();
+ 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();
}
@@ -163,15 +185,6 @@ namespace gr {
{
// Hold global mutex during plan construction and destruction.
planner::scoped_lock lock(planner::mutex());
- const std::string wisdom_lock_file = wisdom_filename() + ".lock";
- int fd = open(wisdom_lock_file.c_str(),
- O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK,
- 0666);
- if (fd < 0) {
- throw std::exception();
- }
- close(fd);
- wisdom_lock = boost::interprocess::file_lock(wisdom_lock_file.c_str());
assert (sizeof (fftwf_complex) == sizeof (gr_complex));
diff --git a/gr-fft/python/fft/CMakeLists.txt b/gr-fft/python/fft/CMakeLists.txt
index f08aebc11d..acf81ca050 100644
--- a/gr-fft/python/fft/CMakeLists.txt
+++ b/gr-fft/python/fft/CMakeLists.txt
@@ -35,6 +35,9 @@ if(ENABLE_TESTING)
set(GR_TEST_LIBRARY_DIRS "")
set(GR_TEST_PYTHON_DIRS
${CMAKE_BINARY_DIR}/gnuradio-runtime/python
+ ${CMAKE_BINARY_DIR}/gnuradio-runtime/swig
+ ${CMAKE_BINARY_DIR}/gr-blocks/swig
+ ${CMAKE_BINARY_DIR}/gr-fft/swig
)
include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")