summaryrefslogtreecommitdiff
path: root/gr-fft
diff options
context:
space:
mode:
Diffstat (limited to 'gr-fft')
-rw-r--r--gr-fft/CMakeLists.txt111
-rw-r--r--gr-fft/doc/CMakeLists.txt23
-rw-r--r--gr-fft/doc/README.fft13
-rw-r--r--gr-fft/doc/fft.dox29
-rw-r--r--gr-fft/gnuradio-fft.pc.in11
-rw-r--r--gr-fft/grc/CMakeLists.txt26
-rw-r--r--gr-fft/grc/fft_block_tree.xml36
-rw-r--r--gr-fft/grc/fft_vxx.xml88
-rw-r--r--gr-fft/grc/goertzel_fc.xml37
-rw-r--r--gr-fft/include/fft/CMakeLists.txt33
-rw-r--r--gr-fft/include/fft/api.h33
-rw-r--r--gr-fft/include/fft/fft.h195
-rw-r--r--gr-fft/include/fft/fft_vcc.h57
-rw-r--r--gr-fft/include/fft/fft_vfc.h57
-rw-r--r--gr-fft/include/fft/goertzel.h64
-rw-r--r--gr-fft/include/fft/goertzel_fc.h57
-rw-r--r--gr-fft/lib/CMakeLists.txt59
-rw-r--r--gr-fft/lib/fft.cc338
-rw-r--r--gr-fft/lib/fft_vcc_fftw.cc147
-rw-r--r--gr-fft/lib/fft_vcc_fftw.h60
-rw-r--r--gr-fft/lib/fft_vfc_fftw.cc124
-rw-r--r--gr-fft/lib/fft_vfc_fftw.h59
-rw-r--r--gr-fft/lib/goertzel.cc84
-rw-r--r--gr-fft/lib/goertzel_fc_impl.cc85
-rw-r--r--gr-fft/lib/goertzel_fc_impl.h60
-rw-r--r--gr-fft/python/CMakeLists.txt47
-rw-r--r--gr-fft/python/__init__.py28
-rwxr-xr-xgr-fft/python/qa_fft.py213
-rwxr-xr-xgr-fft/python/qa_goertzel.py65
-rw-r--r--gr-fft/swig/CMakeLists.txt51
-rw-r--r--gr-fft/swig/fft_swig.i42
31 files changed, 2332 insertions, 0 deletions
diff --git a/gr-fft/CMakeLists.txt b/gr-fft/CMakeLists.txt
new file mode 100644
index 000000000..9ee338341
--- /dev/null
+++ b/gr-fft/CMakeLists.txt
@@ -0,0 +1,111 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup dependencies
+########################################################################
+include(GrBoost)
+
+find_package(FFTW3f)
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+
+GR_REGISTER_COMPONENT("gr-fft" ENABLE_GR_FFT
+ ENABLE_GRUEL
+ ENABLE_VOLK
+ Boost_FOUND
+ ENABLE_GR_CORE
+ FFTW3F_FOUND
+)
+
+GR_SET_GLOBAL(GR_FFT_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GR_FFT)
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_SET(CPACK_COMPONENT_GROUP_FFT_DESCRIPTION "GNU Radio FFT Blocks")
+
+CPACK_COMPONENT("fft_runtime"
+ GROUP "FFT"
+ DISPLAY_NAME "Runtime"
+ DESCRIPTION "Runtime"
+ DEPENDS "core_runtime"
+)
+
+CPACK_COMPONENT("fft_devel"
+ GROUP "FFT"
+ DISPLAY_NAME "Development"
+ DESCRIPTION "C++ headers, package config, import libraries"
+ DEPENDS "core_devel"
+)
+
+CPACK_COMPONENT("fft_python"
+ GROUP "FFT"
+ DISPLAY_NAME "Python"
+ DESCRIPTION "Python modules for runtime; GRC xml files"
+ DEPENDS "core_python;fft_runtime"
+)
+
+CPACK_COMPONENT("fft_swig"
+ GROUP "FFT"
+ DISPLAY_NAME "SWIG"
+ DESCRIPTION "SWIG development .i files"
+ DEPENDS "core_swig;fft_python;fft_devel"
+)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(include/fft)
+add_subdirectory(lib)
+if(ENABLE_PYTHON)
+ add_subdirectory(swig)
+ add_subdirectory(python)
+# add_subdirectory(grc)
+endif(ENABLE_PYTHON)
+#add_subdirectory(examples)
+#add_subdirectory(doc)
+
+########################################################################
+# Create Pkg Config File
+########################################################################
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-fft.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "fft_devel"
+)
+
+endif(ENABLE_GR_FFT)
diff --git a/gr-fft/doc/CMakeLists.txt b/gr-fft/doc/CMakeLists.txt
new file mode 100644
index 000000000..96c42f030
--- /dev/null
+++ b/gr-fft/doc/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+install(
+ FILES README.fft
+ DESTINATION ${GR_PKG_DOC_DIR}
+)
diff --git a/gr-fft/doc/README.fft b/gr-fft/doc/README.fft
new file mode 100644
index 000000000..3ea9e81f8
--- /dev/null
+++ b/gr-fft/doc/README.fft
@@ -0,0 +1,13 @@
+This is the gr-fft package. It contains signal processing blocks to
+perform FFTs and FFT-related functionality.
+
+The Python namespace is in gnuradio.fft, which would be normally
+imported as:
+
+ from gnuradio import fft
+
+See the Doxygen documentation for details about the blocks available
+in this package. A quick listing of the details can be found in Python
+after importing by using:
+
+ help(fft)
diff --git a/gr-fft/doc/fft.dox b/gr-fft/doc/fft.dox
new file mode 100644
index 000000000..5bf612d84
--- /dev/null
+++ b/gr-fft/doc/fft.dox
@@ -0,0 +1,29 @@
+/*! \page page_fft FFT Signal Processing Blocks
+
+\section Introduction
+
+This is the gr-fft package. It contains signal processing blocks to
+perform FFTs and FFT-related functionality.
+
+The Python namespace is in gnuradio.fft, which would be normally
+imported as:
+
+\code
+ from gnuradio import fft
+\endcode
+
+See the Doxygen documentation for details about the blocks available
+in this package. A quick listing of the details can be found in Python
+after importing by using:
+
+\code
+ help(fft)
+\endcode
+
+\section Dependencies
+
+The FFT blocks require the following dependencies.
+
+\li fftw3f (>= 3.0) http://www.fftw.org/download.html
+
+*/
diff --git a/gr-fft/gnuradio-fft.pc.in b/gr-fft/gnuradio-fft.pc.in
new file mode 100644
index 000000000..eb4ddfd9f
--- /dev/null
+++ b/gr-fft/gnuradio-fft.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnuradio-fft
+Description: GNU Radio's FFT signal processing blocks
+Requires: gnuradio-core
+Version: @LIBVER@
+Libs: -L${libdir} -lgnuradio-fft
+Cflags: -I${includedir}
diff --git a/gr-fft/grc/CMakeLists.txt b/gr-fft/grc/CMakeLists.txt
new file mode 100644
index 000000000..632a9aaad
--- /dev/null
+++ b/gr-fft/grc/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+install(FILES
+ fft_block_tree.xml
+ fft_vxx.xml
+ goertzel_fc.xml
+ DESTINATION ${GRC_BLOCKS_DIR}
+ COMPONENT "fft_python"
+)
diff --git a/gr-fft/grc/fft_block_tree.xml b/gr-fft/grc/fft_block_tree.xml
new file mode 100644
index 000000000..3bda77eae
--- /dev/null
+++ b/gr-fft/grc/fft_block_tree.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of GNU Radio
+
+ GNU Radio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Radio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radio; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street,
+ Boston, MA 02110-1301, USA.
+-->
+
+<!--
+###################################################
+##Block Tree for GR FFT blocks.
+###################################################
+ -->
+<cat>
+ <name></name> <!-- Blank for Root Name -->
+ <cat>
+ <name>FFT</name>
+ <block>fft_vxx</block>
+ <block>goertzel_fc</block>
+ </cat>
+</cat>
diff --git a/gr-fft/grc/fft_vxx.xml b/gr-fft/grc/fft_vxx.xml
new file mode 100644
index 000000000..69f12ace7
--- /dev/null
+++ b/gr-fft/grc/fft_vxx.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##FFT
+###################################################
+ -->
+<block>
+ <name>FFT</name>
+ <key>fft_vxx</key>
+ <import>from gnuradio import fft</import>
+ <import>from gnuradio import window</import>
+ <make>#if $type() == "complex"
+fft.fft_vcc($fft_size, $forward, $window, $shift, $nthreads)
+#else
+fft.fft_vfc($fft_size, $forward, $window, $nthreads)
+#end if</make>
+ <callback>set_nthreads($nthreads)</callback>
+ <param>
+ <name>Input Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>hide_shift:</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>hide_shift:all</opt>
+ </option>
+ </param>
+ <param>
+ <name>FFT Size</name>
+ <key>fft_size</key>
+ <value>1024</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Forward/Reverse</name>
+ <key>forward</key>
+ <type>enum</type>
+ <option>
+ <name>Forward</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Reverse</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>window</key>
+ <value>window.blackmanharris(1024)</value>
+ <type>real_vector</type>
+ </param>
+ <param>
+ <name>Shift</name>
+ <key>shift</key>
+ <type>enum</type>
+ <hide>$type.hide_shift</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Num. Threads</name>
+ <key>nthreads</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$fft_size</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$fft_size</vlen>
+ </source>
+</block>
diff --git a/gr-fft/grc/goertzel_fc.xml b/gr-fft/grc/goertzel_fc.xml
new file mode 100644
index 000000000..371284358
--- /dev/null
+++ b/gr-fft/grc/goertzel_fc.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Goertzel
+###################################################
+ -->
+<block>
+ <name>Goertzel</name>
+ <key>goertzel_fc</key>
+ <import>from gnuradio import fft</import>
+ <make>fft.goertzel_fc($rate, $len, $freq)</make>
+ <callback>set_freq($freq)</callback>
+ <callback>set_rate($rate)</callback>
+ <param>
+ <name>Rate</name>
+ <key>rate</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length</name>
+ <key>len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Frequency</name>
+ <key>freq</key>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>float</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-fft/include/fft/CMakeLists.txt b/gr-fft/include/fft/CMakeLists.txt
new file mode 100644
index 000000000..bce3da674
--- /dev/null
+++ b/gr-fft/include/fft/CMakeLists.txt
@@ -0,0 +1,33 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Install header files
+########################################################################
+install(FILES
+ api.h
+ fft.h
+ fft_vcc.h
+ fft_vfc.h
+ goertzel.h
+ goertzel_fc.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft
+ COMPONENT "fft_devel"
+)
+
diff --git a/gr-fft/include/fft/api.h b/gr-fft/include/fft/api.h
new file mode 100644
index 000000000..eef456373
--- /dev/null
+++ b/gr-fft/include/fft/api.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_API_H
+#define INCLUDED_FFT_API_H
+
+#include <gruel/attributes.h>
+
+#ifdef gnuradio_fft_EXPORTS
+# define FFT_API __GR_ATTR_EXPORT
+#else
+# define FFT_API __GR_ATTR_IMPORT
+#endif
+
+#endif /* INCLUDED_FFT_API_H */
diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h
new file mode 100644
index 000000000..5cc2e21e8
--- /dev/null
+++ b/gr-fft/include/fft/fft.h
@@ -0,0 +1,195 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FFT_FFT_H_
+#define _FFT_FFT_H_
+
+/*
+ * Wrappers for FFTW single precision 1d dft
+ */
+
+#include <fft/api.h>
+#include <gr_complex.h>
+#include <boost/thread.hpp>
+
+namespace gr {
+ namespace fft {
+
+
+ /*! \brief Helper function for allocating complex fft buffers
+ */
+ gr_complex* malloc_complex(int size);
+
+ /*! \brief Helper function for allocating float fft buffers
+ */
+ float* malloc_float(int size);
+
+ /*! \brief Helper function for freeing fft buffers
+ */
+ 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
+ */
+ int nthreads() const { return d_nthreads; }
+
+ /*!
+ * compute FFT. The input comes from inbuf, the output is placed in
+ * outbuf.
+ */
+ void execute();
+ };
+
+ /*!
+ * \brief FFT: real in, complex out
+ * \ingroup misc
+ */
+ 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();
+ };
+
+ /*!
+ * \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.
+ */
+ 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 */
+} /*namespace gr */
+
+#endif /* _FFT_FFT_H_ */
diff --git a/gr-fft/include/fft/fft_vcc.h b/gr-fft/include/fft/fft_vcc.h
new file mode 100644
index 000000000..561ae858d
--- /dev/null
+++ b/gr-fft/include/fft/fft_vcc.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_FFT_VCC_H
+#define INCLUDED_FFT_FFT_VCC_H
+
+#include <fft/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace fft {
+
+ class FFT_API fft_vcc : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::fft::fft_vcc::sptr
+ typedef boost::shared_ptr<fft_vcc> sptr;
+
+ /*!
+ * \brief Compute forward or reverse FFT. complex vector in / complex vector out.
+ * \ingroup dft_blk
+ */
+ static FFT_API 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 int nthreads() const = 0;
+
+ virtual bool set_window(const std::vector<float> &window) = 0;
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
+
+#endif /* INCLUDED_FFT_FFT_VCC_H */
diff --git a/gr-fft/include/fft/fft_vfc.h b/gr-fft/include/fft/fft_vfc.h
new file mode 100644
index 000000000..fc48ceefe
--- /dev/null
+++ b/gr-fft/include/fft/fft_vfc.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_FFT_VFC_H
+#define INCLUDED_FFT_FFT_VFC_H
+
+#include <fft/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace fft {
+
+ class FFT_API fft_vfc : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::fft::fft_vfc::sptr
+ typedef boost::shared_ptr<fft_vfc> sptr;
+
+ /*!
+ * \brief Compute forward or reverse FFT. float vector in / complex vector out.
+ * \ingroup dft_blk
+ */
+ static FFT_API sptr make(int fft_size, bool forward,
+ const std::vector<float> &window,
+ int nthreads=1);
+
+ virtual void set_nthreads(int n) = 0;
+
+ virtual int nthreads() const = 0;
+
+ virtual bool set_window(const std::vector<float> &window) = 0;
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
+
+#endif /* INCLUDED_FFT_FFT_VFC_H */
diff --git a/gr-fft/include/fft/goertzel.h b/gr-fft/include/fft/goertzel.h
new file mode 100644
index 000000000..ff37355e6
--- /dev/null
+++ b/gr-fft/include/fft/goertzel.h
@@ -0,0 +1,64 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_IMPL_GOERTZEL_H
+#define INCLUDED_FFT_IMPL_GOERTZEL_H
+
+#include <fft/api.h>
+#include <gr_types.h>
+
+namespace gr {
+ namespace fft {
+
+ /*!
+ * \brief Implements Goertzel single-bin DFT calculation
+ * \ingroup misc
+ */
+ class FFT_API goertzel
+ {
+ public:
+ goertzel(){}
+ 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/fft/goertzel_fc.h b/gr-fft/include/fft/goertzel_fc.h
new file mode 100644
index 000000000..4d3fa8dcf
--- /dev/null
+++ b/gr-fft/include/fft/goertzel_fc.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_GOERTZEL_FC_H
+#define INCLUDED_FFT_GOERTZEL_FC_H
+
+#include <fft/api.h>
+#include <gr_sync_decimator.h>
+
+namespace gr {
+ namespace fft {
+
+ class FFT_API goertzel_fc : virtual public gr_sync_decimator
+ {
+ public:
+
+ // gr::fft::goertzel_fc::sptr
+ typedef boost::shared_ptr<goertzel_fc> sptr;
+
+ /*!
+ * \brief Goertzel single-bin DFT calculation.
+ * \ingroup dft_blk
+ */
+ static FFT_API sptr make(int rate, int len, float freq);
+
+ virtual void set_freq (float freq) = 0;
+
+ virtual void set_rate (int rate) = 0;
+
+ virtual float freq() = 0;
+
+ virtual int rate() = 0;
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
+
+#endif /* INCLUDED_FFT_GOERTZEL_FC_H */
diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt
new file mode 100644
index 000000000..e2f17a183
--- /dev/null
+++ b/gr-fft/lib/CMakeLists.txt
@@ -0,0 +1,59 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup the include and linker paths
+########################################################################
+include_directories(
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+include_directories(${FFT_INCLUDE_DIRS})
+link_directories(${FFT_LIBRARY_DIRS})
+
+include_directories(${Boost_INCLUDE_DIRS})
+link_directories(${Boost_LIBRARY_DIRS})
+
+include_directories(${FFTW3F_INCLUDE_DIRS})
+link_directories(${FFTW3F_LIBRARY_DIRS})
+
+########################################################################
+# Setup library
+########################################################################
+list(APPEND fft_sources
+ fft.cc
+ fft_vcc_fftw.cc
+ fft_vfc_fftw.cc
+ goertzel_fc_impl.cc
+ goertzel.cc
+)
+
+list(APPEND fft_libs
+ gnuradio-core
+ ${Boost_LIBRARIES}
+ ${FFT_LIBRARIES}
+ ${FFTW3F_LIBRARIES}
+)
+
+add_library(gnuradio-fft SHARED ${fft_sources})
+target_link_libraries(gnuradio-fft ${fft_libs})
+GR_LIBRARY_FOO(gnuradio-fft RUNTIME_COMPONENT "fft_runtime" DEVEL_COMPONENT "fft_devel")
diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc
new file mode 100644
index 000000000..6074236e1
--- /dev/null
+++ b/gr-fft/lib/fft.cc
@@ -0,0 +1,338 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2008,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <fft/fft.h>
+#include <gr_sys_paths.h>
+#include <fftw3.h>
+
+#ifdef _MSC_VER //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))
+#endif //_MSC_VER
+
+#include <gr_complex.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <cassert>
+#include <stdexcept>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+namespace fs = boost::filesystem;
+
+namespace gr {
+ namespace fft {
+
+ gr_complex *
+ malloc_complex(int size)
+ {
+ return (gr_complex*)fftwf_malloc(sizeof(gr_complex)*size);
+ }
+
+ float *
+ malloc_float(int size)
+ {
+ return (float*)fftwf_malloc(sizeof(float)*size);
+ }
+
+ void
+ free(void *b)
+ {
+ fftwf_free(b);
+ }
+
+ boost::mutex &
+ planner::mutex()
+ {
+ static boost::mutex s_planning_mutex;
+
+ return s_planning_mutex;
+ }
+
+ static const char *
+ wisdom_filename()
+ {
+ static fs::path path;
+ path = fs::path(gr_appdata_path()) / ".gr_fftw_wisdom";
+ return path.string().c_str();
+ }
+
+ static void
+ import_wisdom()
+ {
+ const char *filename = wisdom_filename ();
+ FILE *fp = fopen (filename, "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);
+ }
+ }
+ }
+
+ 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();
+ }
+
+ fftwf_plan_with_nthreads(nthreads);
+#endif
+ }
+
+ static void
+ export_wisdom()
+ {
+ const char *filename = wisdom_filename ();
+ FILE *fp = fopen (filename, "w");
+ if (fp != 0){
+ fftwf_export_wisdom_to_file (fp);
+ fclose (fp);
+ }
+ else {
+ fprintf (stderr, "fft_impl_fftw: ");
+ perror (filename);
+ }
+ }
+
+// ----------------------------------------------------------------
+
+ 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 *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
+ if (d_inbuf == 0)
+ throw std::runtime_error ("fftwf_malloc");
+
+ d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
+ if (d_outbuf == 0){
+ fftwf_free (d_inbuf);
+ throw std::runtime_error ("fftwf_malloc");
+ }
+
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ 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) {
+ fprintf(stderr, "gr::fft: error creating plan\n");
+ throw std::runtime_error ("fftwf_plan_dft_1d failed");
+ }
+ export_wisdom(); // store new wisdom to disk
+ }
+
+ 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);
+ fftwf_free (d_inbuf);
+ fftwf_free (d_outbuf);
+ }
+
+ void
+ fft_complex::set_nthreads(int n)
+ {
+ if (n <= 0)
+ throw std::out_of_range ("gr::fft: invalid number of threads");
+ d_nthreads = n;
+
+#ifdef FFTW3F_THREADS
+ fftwf_plan_with_nthreads(d_nthreads);
+#endif
+ }
+
+ 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());
+
+ assert (sizeof (fftwf_complex) == sizeof (gr_complex));
+
+ if (fft_size <= 0)
+ throw std::out_of_range ("gr::fft: invalid fft_size");
+
+ d_fft_size = fft_size;
+ d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ());
+ if (d_inbuf == 0)
+ throw std::runtime_error ("fftwf_malloc");
+
+ d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
+ if (d_outbuf == 0){
+ fftwf_free (d_inbuf);
+ throw std::runtime_error ("fftwf_malloc");
+ }
+
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ 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);
+
+ 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
+ }
+
+ 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);
+ fftwf_free (d_inbuf);
+ fftwf_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");
+ d_nthreads = n;
+
+#ifdef FFTW3F_THREADS
+ fftwf_plan_with_nthreads(d_nthreads);
+#endif
+ }
+
+ void
+ fft_real_fwd::execute()
+ {
+ fftwf_execute ((fftwf_plan) d_plan);
+ }
+
+ // ----------------------------------------------------------------
+
+ fft_real_rev::fft_real_rev(int fft_size, int nthreads)
+ {
+ // 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 *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
+ if (d_inbuf == 0)
+ throw std::runtime_error ("fftwf_malloc");
+
+ d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ());
+ if (d_outbuf == 0){
+ fftwf_free (d_inbuf);
+ throw std::runtime_error ("fftwf_malloc");
+ }
+
+ d_nthreads = nthreads;
+ config_threading(nthreads);
+ 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
+ }
+
+ 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);
+ fftwf_free (d_inbuf);
+ fftwf_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);
+#endif
+ }
+
+ void
+ fft_real_rev::execute ()
+ {
+ fftwf_execute ((fftwf_plan) d_plan);
+ }
+
+ } /* namespace fft */
+} /* namespace gr */
diff --git a/gr-fft/lib/fft_vcc_fftw.cc b/gr-fft/lib/fft_vcc_fftw.cc
new file mode 100644
index 000000000..ebcd5ec53
--- /dev/null
+++ b/gr-fft/lib/fft_vcc_fftw.cc
@@ -0,0 +1,147 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fft_vcc_fftw.h"
+#include <gr_io_signature.h>
+#include <math.h>
+#include <string.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)
+ : gr_sync_block("fft_vcc_fftw",
+ gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)),
+ gr_make_io_signature(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);
+ }
+
+ 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;
+ for(unsigned int i = 0; i < offset; i++) // apply window
+ dst[i+fft_m_offset] = in[i] * d_window[i];
+ for(unsigned int i = offset; i < d_fft_size; i++) // apply window
+ dst[i-offset] = in[i] * d_window[i];
+ }
+ else {
+ for(unsigned int i = 0; i < d_fft_size; i++) // apply window
+ dst[i] = in[i] * d_window[i];
+ }
+ }
+ else {
+ if(!d_forward && d_shift) { // apply an ifft shift on the data
+ gr_complex *dst = d_fft->get_inbuf();
+ unsigned int len = (unsigned int)(floor(d_fft_size/2.0)); // half length of complex array
+ memcpy(&dst[0], &in[len], sizeof(gr_complex)*(d_fft_size - len));
+ memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex)*len);
+ }
+ else {
+ memcpy(d_fft->get_inbuf(), in, input_data_size);
+ }
+ }
+
+ // compute the fft
+ d_fft->execute();
+
+ // copy result to our output
+ if(d_forward && d_shift) { // apply a fft shift on the data
+ unsigned int len = (unsigned int)(ceil(d_fft_size/2.0));
+ memcpy(&out[0], &d_fft->get_outbuf()[len], sizeof(gr_complex)*(d_fft_size - len));
+ memcpy(&out[d_fft_size - len], &d_fft->get_outbuf()[0], sizeof(gr_complex)*len);
+ }
+ else {
+ memcpy (out, d_fft->get_outbuf (), output_data_size);
+ }
+
+ in += d_fft_size;
+ out += d_fft_size;
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace fft */
+} /* namespace gr */
diff --git a/gr-fft/lib/fft_vcc_fftw.h b/gr-fft/lib/fft_vcc_fftw.h
new file mode 100644
index 000000000..ea15dd07b
--- /dev/null
+++ b/gr-fft/lib/fft_vcc_fftw.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H
+#define INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H
+
+#include <fft/fft_vcc.h>
+#include <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 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
new file mode 100644
index 000000000..8f9b127e5
--- /dev/null
+++ b/gr-fft/lib/fft_vfc_fftw.cc
@@ -0,0 +1,124 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fft_vfc_fftw.h"
+#include <gr_io_signature.h>
+#include <math.h>
+#include <string.h>
+
+namespace gr {
+ namespace fft {
+
+ fft_vfc::sptr fft_vfc::make(int fft_size, bool forward,
+ const std::vector<float> &window,
+ int nthreads)
+ {
+ return gnuradio::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)
+ : gr_sync_block("fft_vfc_fftw",
+ gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex))),
+ d_fft_size(fft_size), d_forward(forward)
+ {
+ d_fft = new fft_complex(d_fft_size, forward, nthreads);
+ }
+
+ fft_vfc_fftw::~fft_vfc_fftw()
+ {
+ delete d_fft;
+ }
+
+ void
+ fft_vfc_fftw::set_nthreads(int n)
+ {
+ d_fft->set_nthreads(n);
+ }
+
+ int
+ fft_vfc_fftw::nthreads() const
+ {
+ return d_fft->nthreads();
+ }
+
+ bool
+ fft_vfc_fftw::set_window(const std::vector<float> &window)
+ {
+ if(window.size()==0 || window.size()==d_fft_size) {
+ d_window=window;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ int
+ fft_vfc_fftw::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float *)input_items[0];
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ unsigned int output_data_size = output_signature()->sizeof_stream_item (0);
+
+ int count = 0;
+
+ while(count++ < noutput_items) {
+
+ // copy input into optimally aligned buffer
+ if(d_window.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];
+ }
+
+ // compute the fft
+ d_fft->execute();
+
+ // copy result to output stream
+ memcpy(out, d_fft->get_outbuf(), output_data_size);
+
+ in += d_fft_size;
+ out += d_fft_size;
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace fft */
+} /* namespace gr */
+
diff --git a/gr-fft/lib/fft_vfc_fftw.h b/gr-fft/lib/fft_vfc_fftw.h
new file mode 100644
index 000000000..1b6f78ba6
--- /dev/null
+++ b/gr-fft/lib/fft_vfc_fftw.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2007,2008,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H
+#define INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H
+
+#include <fft/fft_vfc.h>
+#include <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 gr */
+
+#endif /* INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H */
diff --git a/gr-fft/lib/goertzel.cc b/gr-fft/lib/goertzel.cc
new file mode 100644
index 000000000..4bcd5ee19
--- /dev/null
+++ b/gr-fft/lib/goertzel.cc
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cmath>
+#include <fft/goertzel.h>
+
+namespace gr {
+ namespace fft {
+
+ 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;
+
+ float w = 2.0*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;
+
+ for(int i = 0; i < d_len; i++)
+ input(in[i]);
+
+ 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++;
+ }
+
+ 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
new file mode 100644
index 000000000..ee214f24d
--- /dev/null
+++ b/gr-fft/lib/goertzel_fc_impl.cc
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2010-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "goertzel_fc_impl.h"
+#include <gr_io_signature.h>
+
+namespace gr {
+ 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_impl::goertzel_fc_impl(int rate, int len, float freq)
+ : gr_sync_decimator("goertzel_fc",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (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()
+ {
+ }
+
+ 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];
+
+ for(int i = 0; i < noutput_items; i++) {
+ *out++ = d_goertzel.batch(in);
+ in += d_len;
+ }
+
+ 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
new file mode 100644
index 000000000..426bc71f6
--- /dev/null
+++ b/gr-fft/lib/goertzel_fc_impl.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2011,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_FFT_GOERTZEL_FC_IMPL_H
+#define INCLUDED_FFT_GOERTZEL_FC_IMPL_H
+
+#include <fft/goertzel_fc.h>
+#include <fft/goertzel.h>
+
+namespace gr {
+ namespace fft {
+
+ 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);
+
+ ~goertzel_fc_impl();
+
+ void set_freq(float freq);
+ void set_rate(int 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);
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
+
+#endif /* INCLUDED_FFT_GOERTZEL_FC_IMPL_H */
+
diff --git a/gr-fft/python/CMakeLists.txt b/gr-fft/python/CMakeLists.txt
new file mode 100644
index 000000000..16c29e599
--- /dev/null
+++ b/gr-fft/python/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+include(GrPython)
+
+GR_PYTHON_INSTALL(
+ FILES
+ __init__.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft
+ COMPONENT "fft_python"
+)
+
+########################################################################
+# Handle the unit tests
+########################################################################
+if(ENABLE_TESTING)
+include(GrTest)
+file(GLOB py_qa_test_files "qa_*.py")
+foreach(py_qa_test_file ${py_qa_test_files})
+ get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
+ set(GR_TEST_PYTHON_DIRS
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/python
+ ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig
+ ${CMAKE_BINARY_DIR}/gr-fft/python
+ ${CMAKE_BINARY_DIR}/gr-fft/swig
+ )
+ set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-fft)
+ GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file})
+endforeach(py_qa_test_file)
+endif(ENABLE_TESTING)
diff --git a/gr-fft/python/__init__.py b/gr-fft/python/__init__.py
new file mode 100644
index 000000000..0fa643e35
--- /dev/null
+++ b/gr-fft/python/__init__.py
@@ -0,0 +1,28 @@
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+'''
+This is the gr-fft package. This package provides GNU Radio
+processing blocks for FFT and related functions.
+'''
+
+from fft_swig import *
+
diff --git a/gr-fft/python/qa_fft.py b/gr-fft/python/qa_fft.py
new file mode 100755
index 000000000..1c45ac148
--- /dev/null
+++ b/gr-fft/python/qa_fft.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python
+#
+# Copyright 2008,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from gnuradio import gr, gr_unittest
+import fft_swig as fft
+import sys
+import random
+
+primes = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,
+ 59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,
+ 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,
+ 227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311)
+
+
+class test_fft(gr_unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def assert_fft_ok2(self, expected_result, result_data):
+ expected_result = expected_result[:len(result_data)]
+ self.assertComplexTuplesAlmostEqual2 (expected_result, result_data,
+ abs_eps=1e-9, rel_eps=4e-4)
+
+ def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4):
+ expected_result = expected_result[:len(result_data)]
+ self.assertFloatTuplesAlmostEqual2 (expected_result, result_data,
+ abs_eps, rel_eps)
+
+ def test_001(self):
+ tb = gr.top_block()
+ fft_size = 32
+ src_data = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)])
+
+ expected_result = ((4377+4516j),
+ (-1706.1268310546875+1638.4256591796875j),
+ (-915.2083740234375+660.69427490234375j),
+ (-660.370361328125+381.59600830078125j),
+ (-499.96044921875+238.41630554199219j),
+ (-462.26748657226562+152.88948059082031j),
+ (-377.98440551757812+77.5928955078125j),
+ (-346.85821533203125+47.152004241943359j),
+ (-295+20j),
+ (-286.33609008789062-22.257017135620117j),
+ (-271.52999877929688-33.081821441650391j),
+ (-224.6358642578125-67.019538879394531j),
+ (-244.24473571777344-91.524826049804688j),
+ (-203.09068298339844-108.54627227783203j),
+ (-198.45195007324219-115.90768432617188j),
+ (-182.97744750976562-128.12318420410156j),
+ (-167-180j),
+ (-130.33688354492188-173.83778381347656j),
+ (-141.19784545898438-190.28807067871094j),
+ (-111.09677124023438-214.48896789550781j),
+ (-70.039543151855469-242.41630554199219j),
+ (-68.960540771484375-228.30015563964844j),
+ (-53.049201965332031-291.47097778320312j),
+ (-28.695289611816406-317.64553833007812j),
+ (57-300j),
+ (45.301143646240234-335.69509887695312j),
+ (91.936195373535156-373.32437133789062j),
+ (172.09465026855469-439.275146484375j),
+ (242.24473571777344-504.47515869140625j),
+ (387.81732177734375-666.6788330078125j),
+ (689.48553466796875-918.2142333984375j),
+ (1646.539306640625-1694.1956787109375j))
+
+ src = gr.vector_source_c(src_data)
+ s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size)
+ op = fft.fft_vcc(fft_size, True, [], False)
+ v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size)
+ dst = gr.vector_sink_c()
+ tb.connect(src, s2v, op, v2s, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_002(self):
+ tb = gr.top_block()
+ fft_size = 32
+
+ tmp_data = ((4377+4516j),
+ (-1706.1268310546875+1638.4256591796875j),
+ (-915.2083740234375+660.69427490234375j),
+ (-660.370361328125+381.59600830078125j),
+ (-499.96044921875+238.41630554199219j),
+ (-462.26748657226562+152.88948059082031j),
+ (-377.98440551757812+77.5928955078125j),
+ (-346.85821533203125+47.152004241943359j),
+ (-295+20j),
+ (-286.33609008789062-22.257017135620117j),
+ (-271.52999877929688-33.081821441650391j),
+ (-224.6358642578125-67.019538879394531j),
+ (-244.24473571777344-91.524826049804688j),
+ (-203.09068298339844-108.54627227783203j),
+ (-198.45195007324219-115.90768432617188j),
+ (-182.97744750976562-128.12318420410156j),
+ (-167-180j),
+ (-130.33688354492188-173.83778381347656j),
+ (-141.19784545898438-190.28807067871094j),
+ (-111.09677124023438-214.48896789550781j),
+ (-70.039543151855469-242.41630554199219j),
+ (-68.960540771484375-228.30015563964844j),
+ (-53.049201965332031-291.47097778320312j),
+ (-28.695289611816406-317.64553833007812j),
+ (57-300j),
+ (45.301143646240234-335.69509887695312j),
+ (91.936195373535156-373.32437133789062j),
+ (172.09465026855469-439.275146484375j),
+ (242.24473571777344-504.47515869140625j),
+ (387.81732177734375-666.6788330078125j),
+ (689.48553466796875-918.2142333984375j),
+ (1646.539306640625-1694.1956787109375j))
+
+ src_data = tuple([x/fft_size for x in tmp_data])
+
+ expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)])
+
+ src = gr.vector_source_c(src_data)
+ s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size)
+ op = fft.fft_vcc(fft_size, False, [], False)
+ v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size)
+ dst = gr.vector_sink_c()
+ tb.connect(src, s2v, op, v2s, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_003(self):
+ # Same test as above, only use 2 threads
+
+ tb = gr.top_block()
+ fft_size = 32
+
+ tmp_data = ((4377+4516j),
+ (-1706.1268310546875+1638.4256591796875j),
+ (-915.2083740234375+660.69427490234375j),
+ (-660.370361328125+381.59600830078125j),
+ (-499.96044921875+238.41630554199219j),
+ (-462.26748657226562+152.88948059082031j),
+ (-377.98440551757812+77.5928955078125j),
+ (-346.85821533203125+47.152004241943359j),
+ (-295+20j),
+ (-286.33609008789062-22.257017135620117j),
+ (-271.52999877929688-33.081821441650391j),
+ (-224.6358642578125-67.019538879394531j),
+ (-244.24473571777344-91.524826049804688j),
+ (-203.09068298339844-108.54627227783203j),
+ (-198.45195007324219-115.90768432617188j),
+ (-182.97744750976562-128.12318420410156j),
+ (-167-180j),
+ (-130.33688354492188-173.83778381347656j),
+ (-141.19784545898438-190.28807067871094j),
+ (-111.09677124023438-214.48896789550781j),
+ (-70.039543151855469-242.41630554199219j),
+ (-68.960540771484375-228.30015563964844j),
+ (-53.049201965332031-291.47097778320312j),
+ (-28.695289611816406-317.64553833007812j),
+ (57-300j),
+ (45.301143646240234-335.69509887695312j),
+ (91.936195373535156-373.32437133789062j),
+ (172.09465026855469-439.275146484375j),
+ (242.24473571777344-504.47515869140625j),
+ (387.81732177734375-666.6788330078125j),
+ (689.48553466796875-918.2142333984375j),
+ (1646.539306640625-1694.1956787109375j))
+
+ src_data = tuple([x/fft_size for x in tmp_data])
+
+ expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)])
+
+ nthreads = 2
+
+ src = gr.vector_source_c(src_data)
+ s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size)
+ op = fft.fft_vcc(fft_size, False, [], False, nthreads)
+ v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size)
+ dst = gr.vector_sink_c()
+ tb.connect(src, s2v, op, v2s, dst)
+ tb.run()
+ result_data = dst.data()
+ self.assert_fft_ok2(expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_fft, "test_fft.xml")
+
diff --git a/gr-fft/python/qa_goertzel.py b/gr-fft/python/qa_goertzel.py
new file mode 100755
index 000000000..27f9d370e
--- /dev/null
+++ b/gr-fft/python/qa_goertzel.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+from math import pi, cos
+import fft_swig as fft
+
+class test_goertzel(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def make_tone_data(self, rate, freq):
+ return [cos(2*pi*x*freq/rate) for x in range(rate)]
+
+ def transform(self, src_data, rate, freq):
+ src = gr.vector_source_f(src_data, False)
+ dft = fft.goertzel_fc(rate, rate, freq)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, dft, dst)
+ self.tb.run()
+ return dst.data()
+
+ def test_001(self): # Measure single tone magnitude
+ rate = 8000
+ freq = 100
+ bin = freq
+ src_data = self.make_tone_data(rate, freq)
+ expected_result = 0.5
+ actual_result = abs(self.transform(src_data, rate, bin)[0])
+ self.assertAlmostEqual(expected_result, actual_result, places=4)
+
+ def test_002(self): # Measure off frequency magnitude
+ rate = 8000
+ freq = 100
+ bin = freq/2
+ src_data = self.make_tone_data(rate, freq)
+ expected_result = 0.0
+ actual_result = abs(self.transform(src_data, rate, bin)[0])
+ self.assertAlmostEqual(expected_result, actual_result, places=4)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_goertzel, "test_goertzel.xml")
diff --git a/gr-fft/swig/CMakeLists.txt b/gr-fft/swig/CMakeLists.txt
new file mode 100644
index 000000000..63f5dfb0e
--- /dev/null
+++ b/gr-fft/swig/CMakeLists.txt
@@ -0,0 +1,51 @@
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Setup swig generation
+########################################################################
+include(GrPython)
+include(GrSwig)
+
+set(GR_SWIG_INCLUDE_DIRS
+ ${GR_FFT_INCLUDE_DIRS}
+ ${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
+)
+
+set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
+
+set(GR_SWIG_LIBRARIES gnuradio-fft)
+
+GR_SWIG_MAKE(fft_swig fft_swig.i)
+
+GR_SWIG_INSTALL(
+ TARGETS fft_swig
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft
+ COMPONENT "fft_python"
+)
+
+install(
+ FILES
+ fft_swig.i
+ ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "fft_swig"
+)
diff --git a/gr-fft/swig/fft_swig.i b/gr-fft/swig/fft_swig.i
new file mode 100644
index 000000000..07fab34d4
--- /dev/null
+++ b/gr-fft/swig/fft_swig.i
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define FFT_API
+
+%include "gnuradio.i"
+
+//load generated python docstrings
+%include "fft_swig_doc.i"
+
+%{
+#include "fft/fft_vcc.h"
+#include "fft/fft_vfc.h"
+#include "fft/goertzel_fc.h"
+%}
+
+%include "fft/fft_vcc.h"
+%include "fft/fft_vfc.h"
+%include "fft/goertzel_fc.h"
+
+GR_SWIG_BLOCK_MAGIC2(fft, fft_vcc);
+GR_SWIG_BLOCK_MAGIC2(fft, fft_vfc);
+GR_SWIG_BLOCK_MAGIC2(fft, goertzel_fc);