From f64b971f34ab813f70b0680ec7ae02744343ef3c Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Tue, 1 May 2012 22:10:17 -0400
Subject: filter: work on creating gr-filter top-level component.
Builds but does not bring in libgnuradio-fft.so symbols.
---
CMakeLists.txt | 1 +
gr-filter/CMakeLists.txt | 109 +++++++++++++++++
gr-filter/doc/CMakeLists.txt | 23 ++++
gr-filter/doc/README.filter | 13 ++
gr-filter/doc/filter.dox | 27 +++++
gr-filter/gnuradio-filter.pc.in | 11 ++
gr-filter/grc/CMakeLists.txt | 24 ++++
gr-filter/grc/filter_block_tree.xml | 34 ++++++
gr-filter/include/filter/CMakeLists.txt | 82 +++++++++++++
gr-filter/include/filter/api.h | 33 +++++
gr-filter/include/filter/fft.h | 195 ++++++++++++++++++++++++++++++
gr-filter/include/filter/fft_vcc.h | 57 +++++++++
gr-filter/include/filter/fir_filter_fff.h | 53 ++++++++
gr-filter/lib/CMakeLists.txt | 60 +++++++++
gr-filter/lib/fir_filter_fff_impl.cc | 110 +++++++++++++++++
gr-filter/lib/fir_filter_fff_impl.h | 56 +++++++++
gr-filter/python/CMakeLists.txt | 47 +++++++
gr-filter/python/__init__.py | 28 +++++
gr-filter/python/qa_fir_filter.py | 46 +++++++
gr-filter/swig/CMakeLists.txt | 53 ++++++++
gr-filter/swig/filter_swig.i | 36 ++++++
21 files changed, 1098 insertions(+)
create mode 100644 gr-filter/CMakeLists.txt
create mode 100644 gr-filter/doc/CMakeLists.txt
create mode 100644 gr-filter/doc/README.filter
create mode 100644 gr-filter/doc/filter.dox
create mode 100644 gr-filter/gnuradio-filter.pc.in
create mode 100644 gr-filter/grc/CMakeLists.txt
create mode 100644 gr-filter/grc/filter_block_tree.xml
create mode 100644 gr-filter/include/filter/CMakeLists.txt
create mode 100644 gr-filter/include/filter/api.h
create mode 100644 gr-filter/include/filter/fft.h
create mode 100644 gr-filter/include/filter/fft_vcc.h
create mode 100644 gr-filter/include/filter/fir_filter_fff.h
create mode 100644 gr-filter/lib/CMakeLists.txt
create mode 100644 gr-filter/lib/fir_filter_fff_impl.cc
create mode 100644 gr-filter/lib/fir_filter_fff_impl.h
create mode 100644 gr-filter/python/CMakeLists.txt
create mode 100644 gr-filter/python/__init__.py
create mode 100755 gr-filter/python/qa_fir_filter.py
create mode 100644 gr-filter/swig/CMakeLists.txt
create mode 100644 gr-filter/swig/filter_swig.i
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dad398e8c..9be8217ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -229,6 +229,7 @@ add_subdirectory(gnuradio-core)
add_subdirectory(grc)
add_subdirectory(gr-fft)
+add_subdirectory(gr-filter)
add_subdirectory(gr-atsc)
add_subdirectory(gr-audio)
add_subdirectory(gr-comedi)
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
new file mode 100644
index 000000000..a4d25fd13
--- /dev/null
+++ b/gr-filter/CMakeLists.txt
@@ -0,0 +1,109 @@
+# 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)
+
+########################################################################
+# Register component
+########################################################################
+include(GrComponent)
+
+GR_REGISTER_COMPONENT("gr-filter" ENABLE_GR_FILTER
+ ENABLE_GRUEL
+ ENABLE_VOLK
+ Boost_FOUND
+ ENABLE_GR_CORE
+ ENABLE_GR_FFT
+)
+
+GR_SET_GLOBAL(FILTER_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+########################################################################
+# Begin conditional configuration
+########################################################################
+if(ENABLE_GR_FILTER)
+
+########################################################################
+# Setup CPack components
+########################################################################
+include(GrPackage)
+CPACK_SET(CPACK_COMPONENT_GROUP_FILTER_DESCRIPTION "GNU Radio Filter Blocks")
+
+CPACK_COMPONENT("filter_runtime"
+ GROUP "Filter"
+ DISPLAY_NAME "Runtime"
+ DESCRIPTION "Runtime"
+ DEPENDS "core_runtime"
+)
+
+CPACK_COMPONENT("filter_devel"
+ GROUP "Filter"
+ DISPLAY_NAME "Development"
+ DESCRIPTION "C++ headers, package config, import libraries"
+ DEPENDS "core_devel"
+)
+
+CPACK_COMPONENT("filter_python"
+ GROUP "Filter"
+ DISPLAY_NAME "Python"
+ DESCRIPTION "Python modules for runtime; GRC xml files"
+ DEPENDS "core_python;filter_runtime"
+)
+
+CPACK_COMPONENT("filter_swig"
+ GROUP "Filter"
+ DISPLAY_NAME "SWIG"
+ DESCRIPTION "SWIG development .i files"
+ DEPENDS "core_swig;filter_python;filter_devel"
+)
+
+########################################################################
+# Add subdirectories
+########################################################################
+add_subdirectory(include/filter)
+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-filter.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc
+@ONLY)
+
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc
+ DESTINATION ${GR_LIBRARY_DIR}/pkgconfig
+ COMPONENT "filter_devel"
+)
+
+endif(ENABLE_GR_FILTER)
diff --git a/gr-filter/doc/CMakeLists.txt b/gr-filter/doc/CMakeLists.txt
new file mode 100644
index 000000000..63447ed2c
--- /dev/null
+++ b/gr-filter/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.filter
+ DESTINATION ${GR_PKG_DOC_DIR}
+)
diff --git a/gr-filter/doc/README.filter b/gr-filter/doc/README.filter
new file mode 100644
index 000000000..776acd46c
--- /dev/null
+++ b/gr-filter/doc/README.filter
@@ -0,0 +1,13 @@
+This is the gr-filter package. It contains signal processing blocks to
+perform filtering operations.
+
+The Python namespace is in gnuradio.filter, which would be normally
+imported as:
+
+ from gnuradio import filter
+
+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(filter)
diff --git a/gr-filter/doc/filter.dox b/gr-filter/doc/filter.dox
new file mode 100644
index 000000000..fc3b52e91
--- /dev/null
+++ b/gr-filter/doc/filter.dox
@@ -0,0 +1,27 @@
+/*! \page page_filter filter Signal Processing Blocks
+
+\section Introduction
+
+This is the gr-filter package. It contains signal processing blocks to
+perform filtering operations.
+
+The Python namespace is in gnuradio.filter, which would be normally
+imported as:
+
+\code
+ from gnuradio import filter
+\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(filter)
+\endcode
+
+\section Dependencies
+
+The filter blocks depend on \ref page_fft.
+
+*/
diff --git a/gr-filter/gnuradio-filter.pc.in b/gr-filter/gnuradio-filter.pc.in
new file mode 100644
index 000000000..e4e83b350
--- /dev/null
+++ b/gr-filter/gnuradio-filter.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gnuradio-filter
+Description: GNU Radio's filter signal processing blocks
+Requires: gnuradio-core gnuradio-fft
+Version: @LIBVER@
+Libs: -L${libdir} -lgnuradio-filter
+Cflags: -I${includedir}
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
new file mode 100644
index 000000000..79496183f
--- /dev/null
+++ b/gr-filter/grc/CMakeLists.txt
@@ -0,0 +1,24 @@
+# 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
+ filter_block_tree.xml
+ DESTINATION ${GRC_BLOCKS_DIR}
+ COMPONENT "filter_python"
+)
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
new file mode 100644
index 000000000..a97620db9
--- /dev/null
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+ Filters
+
+
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
new file mode 100644
index 000000000..a3c83f3dc
--- /dev/null
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -0,0 +1,82 @@
+# 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.
+
+########################################################################
+# generate helper scripts to expand templated files
+########################################################################
+include(GrPython)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
+#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_CORE_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_dict2(name, sig, 'filter')
+ build_utils.expand_template(d, inp)
+
+")
+
+macro(expand_h root)
+ #make a list of all the generated files
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+
+ #create a command to generate the files
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #install rules for the generated h files
+ list(APPEND generated_includes ${expanded_files_h})
+endmacro(expand_h)
+
+########################################################################
+# Invoke macro to generate various sources
+#######################################################################
+#expand_h(fir_filter_XXX fff ccc ccf fcc fsf scc)
+
+#add_custom_target(filter_generated_includes DEPENDS
+# ${generated_includes}
+#)
+
+########################################################################
+# Install header files
+########################################################################
+install(FILES
+ api.h
+ fir_filter_fff.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft
+ COMPONENT "fft_devel"
+)
+
diff --git a/gr-filter/include/filter/api.h b/gr-filter/include/filter/api.h
new file mode 100644
index 000000000..025b0bd4a
--- /dev/null
+++ b/gr-filter/include/filter/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_FILTER_API_H
+#define INCLUDED_FILTER_API_H
+
+#include
+
+#ifdef gnuradio_filter_EXPORTS
+# define FILTER_API __GR_ATTR_EXPORT
+#else
+# define FILTER_API __GR_ATTR_IMPORT
+#endif
+
+#endif /* INCLUDED_FILTER_API_H */
diff --git a/gr-filter/include/filter/fft.h b/gr-filter/include/filter/fft.h
new file mode 100644
index 000000000..5cc2e21e8
--- /dev/null
+++ b/gr-filter/include/filter/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
+#include
+#include
+
+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-filter/include/filter/fft_vcc.h b/gr-filter/include/filter/fft_vcc.h
new file mode 100644
index 000000000..561ae858d
--- /dev/null
+++ b/gr-filter/include/filter/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
+#include
+
+namespace gr {
+ namespace fft {
+
+ class FFT_API fft_vcc : virtual public gr_sync_block
+ {
+ public:
+
+ // gr::fft::fft_vcc::sptr
+ typedef boost::shared_ptr 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 &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 &window) = 0;
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
+
+#endif /* INCLUDED_FFT_FFT_VCC_H */
diff --git a/gr-filter/include/filter/fir_filter_fff.h b/gr-filter/include/filter/fir_filter_fff.h
new file mode 100644
index 000000000..5b6d19b34
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter_fff.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 FILTER_FIR_FILTER_FFF_H
+#define FILTER_FIR_FILTER_FFF_H
+
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fir_filter_fff : virtual public gr_sync_decimator
+ {
+ public:
+
+ // gr::filter::fir_filter_fff::sptr
+ typedef boost::shared_ptr sptr;
+
+ /*!
+ * \brief FIR filter with float input, float output, and float taps
+ * \ingroup filter_blk
+ */
+ static FILTER_API sptr make(int decimation,
+ const std::vector &taps);
+
+ virtual void set_taps (const std::vector &taps) = 0;
+ virtual std::vector taps () const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* FILTER_FIR_FILTER_FFF_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
new file mode 100644
index 000000000..0ffdb75fc
--- /dev/null
+++ b/gr-filter/lib/CMakeLists.txt
@@ -0,0 +1,60 @@
+# 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}
+ ${VOLK_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+include_directories(${FILTER_INCLUDE_DIRS})
+link_directories(${FILTER_LIBRARY_DIRS})
+
+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 filter_sources
+ fir_filter_fff_impl.cc
+)
+
+list(APPEND filter_libs
+ gnuradio-core
+ gnuradio-fft
+ ${Boost_LIBRARIES}
+ ${FFTW3F_LIBRARIES}
+ ${VOLK_LIBRARIES}
+)
+
+add_library(gnuradio-filter SHARED ${filter_sources})
+target_link_libraries(gnuradio-filter ${filter_libs})
+GR_LIBRARY_FOO(gnuradio-filter RUNTIME_COMPONENT "filter_runtime" DEVEL_COMPONENT "filter_devel")
+add_dependencies(gnuradio-filter gnuradio-fft filter_generated_includes filter_generated_swigs)
diff --git a/gr-filter/lib/fir_filter_fff_impl.cc b/gr-filter/lib/fir_filter_fff_impl.cc
new file mode 100644
index 000000000..4a1233a24
--- /dev/null
+++ b/gr-filter/lib/fir_filter_fff_impl.cc
@@ -0,0 +1,110 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fir_filter_fff_impl.h"
+#include
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ fir_filter_fff::sptr
+ fir_filter_fff::make(int decimation, const std::vector &taps)
+ {
+ return gnuradio::get_initial_sptr(new fir_filter_fff_impl
+ (decimation, taps));
+ }
+
+
+ fir_filter_fff_impl::fir_filter_fff_impl(int decimation,
+ const std::vector &taps)
+ : gr_sync_decimator("fir_filter_fff",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (1, 1, sizeof(float)),
+ decimation)
+ {
+ set_taps(taps);
+ d_updated = false;
+ set_history(d_ntaps+1);
+ }
+
+ fir_filter_fff_impl::~fir_filter_fff_impl()
+ {
+ }
+
+ void
+ fir_filter_fff_impl::set_taps(const std::vector &taps)
+ {
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_float(d_ntaps);
+ for(int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = taps[i];
+ }
+ d_updated = true;
+ }
+
+ std::vector
+ fir_filter_fff_impl::taps() const
+ {
+ std::vector t;
+ for(int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i]);
+ return t;
+ }
+
+ int
+ fir_filter_fff_impl::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];
+ float *out = (float*)output_items[0];
+
+ if (d_updated) {
+ set_history((unsigned int)d_ntaps+1);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ if (decimation() == 1) {
+ for(int i = 0; i < noutput_items; i++) {
+ volk_32f_x2_dot_prod_32f_u(&out[i], &in[i], d_taps, d_ntaps);
+ }
+
+ //d_fir->filterN(out, in, noutput_items);
+ }
+ else {
+ //d_fir->filterNdec(out, in, noutput_items, decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/fir_filter_fff_impl.h b/gr-filter/lib/fir_filter_fff_impl.h
new file mode 100644
index 000000000..962781466
--- /dev/null
+++ b/gr-filter/lib/fir_filter_fff_impl.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 FILTER_FIR_FILTER_FFF_IMPL_H
+#define FILTER_FIR_FILTER_FFF_IMPL_H
+
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fir_filter_fff_impl : public fir_filter_fff
+ {
+ private:
+ float *d_taps;
+ int d_ntaps;
+ bool d_updated;
+
+ public:
+ fir_filter_fff_impl(int decimation,
+ const std::vector &taps);
+
+ ~fir_filter_fff_impl();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* FILTER_FIR_FILTER_FFF_IMPL_H */
diff --git a/gr-filter/python/CMakeLists.txt b/gr-filter/python/CMakeLists.txt
new file mode 100644
index 000000000..e52cac759
--- /dev/null
+++ b/gr-filter/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/filter
+ COMPONENT "filter_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-filter/python
+ ${CMAKE_BINARY_DIR}/gr-filter/swig
+ )
+ set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-filter)
+ 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-filter/python/__init__.py b/gr-filter/python/__init__.py
new file mode 100644
index 000000000..56dd2dc5a
--- /dev/null
+++ b/gr-filter/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-filter package. This package provides GNU Radio
+processing blocks for FILTER and related functions.
+'''
+
+from filter_swig import *
+
diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py
new file mode 100755
index 000000000..928f17aa3
--- /dev/null
+++ b/gr-filter/python/qa_fir_filter.py
@@ -0,0 +1,46 @@
+#!/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 filter_swig as filter
+
+class test_filter(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block ()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_fir_filter_fff_001(self):
+ src_data = [1, 2, 3, 4]
+ expected_data = [0, 0.5, 1.5, 2.5]
+ src = gr.vector_source_f(src_data)
+ op = filter.fir_filter_fff(1, [0.5, 0.5])
+ dst = gr.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_filter, "test_filter.xml")
+
diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt
new file mode 100644
index 000000000..5dff9f631
--- /dev/null
+++ b/gr-filter/swig/CMakeLists.txt
@@ -0,0 +1,53 @@
+# 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
+ ${FILTER_INCLUDE_DIRS}
+ ${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
+ ${FFT_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
+)
+
+# FIXME: rename to filter_swig_doc.i when gnuradio-core is updated
+set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i)
+set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
+
+set(GR_SWIG_LIBRARIES gnuradio-filter gnuradio-fft)
+
+GR_SWIG_MAKE(filter_swig filter_swig.i)
+
+GR_SWIG_INSTALL(
+ TARGETS filter_swig
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/filter
+ COMPONENT "filter_python"
+)
+
+install(
+ FILES
+ filter_swig.i
+ ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
+ COMPONENT "filter_swig"
+)
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
new file mode 100644
index 000000000..55ee3c56c
--- /dev/null
+++ b/gr-filter/swig/filter_swig.i
@@ -0,0 +1,36 @@
+/* -*- 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 FILTER_API
+
+%include "gnuradio.i"
+
+//load generated python docstrings
+%include "gr_filter_swig_doc.i"
+
+%{
+#include "filter/fir_filter_fff.h"
+%}
+
+%include "filter/fir_filter_fff.h"
+
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
--
cgit
From 7f8331808f99a9747bed39e55bbee98bc58c6038 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 11:45:29 -0400
Subject: build: reworking cmake structure for include and lib directories. I
think this is cleaner.
We also probably don't need the link_directories (according to the cmake guys, this is no longer necessary).
---
gr-fft/lib/CMakeLists.txt | 11 ++++-------
gr-filter/lib/CMakeLists.txt | 16 ++++++----------
gr-wavelet/lib/CMakeLists.txt | 9 +++------
3 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt
index e2f17a183..ea1248fba 100644
--- a/gr-fft/lib/CMakeLists.txt
+++ b/gr-fft/lib/CMakeLists.txt
@@ -21,19 +21,16 @@
# Setup the include and linker paths
########################################################################
include_directories(
- ${GNURADIO_CORE_INCLUDE_DIRS}
- ${GR_FFT_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
)
-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})
########################################################################
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 0ffdb75fc..2850b6925 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -21,22 +21,18 @@
# Setup the include and linker paths
########################################################################
include_directories(
- ${GNURADIO_CORE_INCLUDE_DIRS}
- ${VOLK_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${VOLK_INCLUDE_DIRS}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_FFT_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${FFTW3F_INCLUDE_DIRS}
)
-include_directories(${FILTER_INCLUDE_DIRS})
-link_directories(${FILTER_LIBRARY_DIRS})
-
-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})
########################################################################
diff --git a/gr-wavelet/lib/CMakeLists.txt b/gr-wavelet/lib/CMakeLists.txt
index f0d9068b7..3247c17b5 100644
--- a/gr-wavelet/lib/CMakeLists.txt
+++ b/gr-wavelet/lib/CMakeLists.txt
@@ -21,19 +21,16 @@
# Setup the include and linker paths
########################################################################
include_directories(
- ${GNURADIO_CORE_INCLUDE_DIRS}
${GR_WAVELET_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${Boost_INCLUDE_DIRS}
+ ${GSL_INCLUDE_DIRS}
)
-include_directories(${WAVELET_INCLUDE_DIRS})
link_directories(${WAVELET_LIBRARY_DIRS})
-
-include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
-
-include_directories(${GSL_INCLUDE_DIRS})
link_directories(${GSL_LIBRARY_DIRS})
########################################################################
--
cgit
From 38120d6ba5b805f522e74c0e440e487f673cb82e Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 11:59:25 -0400
Subject: fft: export the FFTW malloc and free helper functions.
---
gr-fft/include/fft/fft.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h
index 5cc2e21e8..e3fd3f278 100644
--- a/gr-fft/include/fft/fft.h
+++ b/gr-fft/include/fft/fft.h
@@ -37,15 +37,15 @@ namespace gr {
/*! \brief Helper function for allocating complex fft buffers
*/
- gr_complex* malloc_complex(int size);
+ FFT_API gr_complex* malloc_complex(int size);
/*! \brief Helper function for allocating float fft buffers
*/
- float* malloc_float(int size);
+ FFT_API float* malloc_float(int size);
/*! \brief Helper function for freeing fft buffers
*/
- void free(void *b);
+ FFT_API void free(void *b);
/*!
* \brief Export reference to planner mutex for those apps that
--
cgit
From 417337cd4a6cef95bbec7c5d04bbacdab0eb9f47 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 12:43:18 -0400
Subject: filter: fixing up fir_filter_fff to handle taps appropriately, also
does decimation.
---
gr-filter/lib/fir_filter_fff_impl.cc | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/gr-filter/lib/fir_filter_fff_impl.cc b/gr-filter/lib/fir_filter_fff_impl.cc
index 4a1233a24..15ccb4d07 100644
--- a/gr-filter/lib/fir_filter_fff_impl.cc
+++ b/gr-filter/lib/fir_filter_fff_impl.cc
@@ -48,6 +48,7 @@ namespace gr {
gr_make_io_signature (1, 1, sizeof(float)),
decimation)
{
+ d_taps = NULL;
set_taps(taps);
d_updated = false;
set_history(d_ntaps+1);
@@ -55,11 +56,21 @@ namespace gr {
fir_filter_fff_impl::~fir_filter_fff_impl()
{
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
}
void
fir_filter_fff_impl::set_taps(const std::vector &taps)
{
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
d_ntaps = (int)taps.size();
d_taps = fft::malloc_float(d_ntaps);
for(int i = 0; i < d_ntaps; i++) {
@@ -95,11 +106,13 @@ namespace gr {
for(int i = 0; i < noutput_items; i++) {
volk_32f_x2_dot_prod_32f_u(&out[i], &in[i], d_taps, d_ntaps);
}
-
- //d_fir->filterN(out, in, noutput_items);
}
else {
- //d_fir->filterNdec(out, in, noutput_items, decimation());
+ int j = 0;
+ for(int i = 0; i < noutput_items; i++) {
+ volk_32f_x2_dot_prod_32f_u(&out[i], &in[j], d_taps, d_ntaps);
+ j += decimation();
+ }
}
return noutput_items;
--
cgit
From a247889d7ad212cf3a69df8ec95dc2436e4cc400 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 12:43:43 -0400
Subject: filter: adding examples folder.
First example compares old filter in gr to new one in filter.
---
gr-filter/examples/CMakeLists.txt | 27 +++++++++++
gr-filter/examples/fir_filter_fff.py | 93 ++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
create mode 100644 gr-filter/examples/CMakeLists.txt
create mode 100755 gr-filter/examples/fir_filter_fff.py
diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt
new file mode 100644
index 000000000..c798a8403
--- /dev/null
+++ b/gr-filter/examples/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011 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)
+
+# Base stuff
+GR_PYTHON_INSTALL(PROGRAMS
+ fir_filter_fff.py
+ DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}
+ COMPONENT "filter_python"
+)
diff --git a/gr-filter/examples/fir_filter_fff.py b/gr-filter/examples/fir_filter_fff.py
new file mode 100755
index 000000000..538aded44
--- /dev/null
+++ b/gr-filter/examples/fir_filter_fff.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fir_filter_fff(gr.top_block):
+ def __init__(self, N, fs, bw, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw = bw
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = gr.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_f(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_float, self._nsamps)
+
+ self.filt0 = filter.fir_filter_fff(self._decim, taps)
+ self.filt1 = gr.fir_filter_fff(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_f()
+ self.vsnk_out = gr.vector_sink_f()
+ self.vsnk_gr = gr.vector_sink_f()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+ self.connect(self.head, self.filt1, self.vsnk_gr)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-B", "--bandwidth", type="eng_float", default=1000,
+ help="Filter bandwidth [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fir_filter_fff(options.nsamples,
+ options.samplerate,
+ options.bandwidth,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+ data_gr = scipy.array(put.vsnk_gr.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_gr, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
--
cgit
From 32f807a8c8f1bcadfd8f8ad4c5a46c1b099f8c8f Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 16:14:09 -0400
Subject: filter: Reworking filter to have a set of basic implementation
classes for filters of different kinds.
The GR blocks are templated now and call from fir_filters for the volk-specific implemenation.
Note the modification to build_utils.py to accomodate these changes.
---
gnuradio-core/src/python/build_utils.py | 32 +++-
gr-filter/CMakeLists.txt | 4 +-
gr-filter/include/filter/CMakeLists.txt | 15 +-
gr-filter/include/filter/fft.h | 195 --------------------
gr-filter/include/filter/fft_vcc.h | 57 ------
gr-filter/include/filter/fir_filter.h | 112 ++++++++++++
gr-filter/include/filter/fir_filter_XXX.h.t | 55 ++++++
gr-filter/include/filter/fir_filter_fff.h | 53 ------
gr-filter/lib/CMakeLists.txt | 69 ++++++-
gr-filter/lib/fir_filter.cc | 268 ++++++++++++++++++++++++++++
gr-filter/lib/fir_filter_XXX_impl.cc.t | 98 ++++++++++
gr-filter/lib/fir_filter_XXX_impl.h.t | 57 ++++++
gr-filter/lib/fir_filter_fff_impl.cc | 123 -------------
gr-filter/lib/fir_filter_fff_impl.h | 56 ------
gr-filter/python/qa_fir_filter.py | 22 +++
gr-filter/swig/CMakeLists.txt | 2 +-
gr-filter/swig/filter_swig.i | 6 +
17 files changed, 729 insertions(+), 495 deletions(-)
delete mode 100644 gr-filter/include/filter/fft.h
delete mode 100644 gr-filter/include/filter/fft_vcc.h
create mode 100644 gr-filter/include/filter/fir_filter.h
create mode 100644 gr-filter/include/filter/fir_filter_XXX.h.t
delete mode 100644 gr-filter/include/filter/fir_filter_fff.h
create mode 100644 gr-filter/lib/fir_filter.cc
create mode 100644 gr-filter/lib/fir_filter_XXX_impl.cc.t
create mode 100644 gr-filter/lib/fir_filter_XXX_impl.h.t
delete mode 100644 gr-filter/lib/fir_filter_fff_impl.cc
delete mode 100644 gr-filter/lib/fir_filter_fff_impl.h
diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py
index 0660941d5..0898f46c4 100644
--- a/gnuradio-core/src/python/build_utils.py
+++ b/gnuradio-core/src/python/build_utils.py
@@ -182,7 +182,37 @@ def standard_dict (name, code3):
d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper ()
d['BASE_NAME'] = re.sub ('^gr_', '', name)
d['SPTR_NAME'] = '%s_sptr' % name
- d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written'
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+
+def standard_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['BASE_NAME'] = name
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
+ d['COPYRIGHT'] = copyright
+ d['TYPE'] = i_type (code3)
+ d['I_TYPE'] = i_type (code3)
+ d['O_TYPE'] = o_type (code3)
+ d['TAP_TYPE'] = tap_type (code3)
+ d['IS_COMPLEX'] = is_complex (code3)
+ return d
+
+def standard_impl_dict2 (name, code3, package):
+ d = {}
+ d['NAME'] = name
+ d['IMPL_NAME'] = name
+ d['BASE_NAME'] = name.rstrip("_impl")
+ d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
+ d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
d['COPYRIGHT'] = copyright
d['TYPE'] = i_type (code3)
d['I_TYPE'] = i_type (code3)
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
index a4d25fd13..02b8f23fe 100644
--- a/gr-filter/CMakeLists.txt
+++ b/gr-filter/CMakeLists.txt
@@ -35,9 +35,11 @@ GR_REGISTER_COMPONENT("gr-filter" ENABLE_GR_FILTER
ENABLE_GR_FFT
)
-GR_SET_GLOBAL(FILTER_INCLUDE_DIRS
+GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_BINARY_DIR}/lib
+ ${CMAKE_CURRENT_BINARY_DIR}/include
)
########################################################################
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index a3c83f3dc..4889312da 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -32,7 +32,7 @@ os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
if __name__ == '__main__':
import build_utils
- root, inp = sys.argv[1:3]
+ root, inp = sys.argv[1:3]
for sig in sys.argv[3:]:
name = re.sub ('X+', sig, root)
d = build_utils.standard_dict2(name, sig, 'filter')
@@ -64,19 +64,20 @@ endmacro(expand_h)
########################################################################
# Invoke macro to generate various sources
#######################################################################
-#expand_h(fir_filter_XXX fff ccc ccf fcc fsf scc)
+expand_h(fir_filter_XXX fff ccf ccc)
-#add_custom_target(filter_generated_includes DEPENDS
-# ${generated_includes}
-#)
+add_custom_target(filter_generated_includes DEPENDS
+ ${generated_includes}
+)
########################################################################
# Install header files
########################################################################
install(FILES
api.h
- fir_filter_fff.h
- DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft
+ fir_filter.h
+ ${generated_includes}
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter
COMPONENT "fft_devel"
)
diff --git a/gr-filter/include/filter/fft.h b/gr-filter/include/filter/fft.h
deleted file mode 100644
index 5cc2e21e8..000000000
--- a/gr-filter/include/filter/fft.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* -*- 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
-#include
-#include
-
-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-filter/include/filter/fft_vcc.h b/gr-filter/include/filter/fft_vcc.h
deleted file mode 100644
index 561ae858d..000000000
--- a/gr-filter/include/filter/fft_vcc.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- 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
-#include
-
-namespace gr {
- namespace fft {
-
- class FFT_API fft_vcc : virtual public gr_sync_block
- {
- public:
-
- // gr::fft::fft_vcc::sptr
- typedef boost::shared_ptr 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 &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 &window) = 0;
- };
-
- } /* namespace fft */
-} /* namespace gr */
-
-#endif /* INCLUDED_FFT_FFT_VCC_H */
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
new file mode 100644
index 000000000..c307fea46
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter.h
@@ -0,0 +1,112 @@
+/* -*- 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.
+ */
+
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+ namespace impl {
+
+ class FILTER_API fir_filter_fff
+ {
+ public:
+ fir_filter_fff(int decimation,
+ const std::vector &taps);
+ ~fir_filter_fff();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+ unsigned int ntaps() const;
+
+ float filter(const float input[]);
+ void filterN(float output[],
+ const float input[],
+ unsigned long n);
+ void filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ float *d_taps;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccf
+ {
+ public:
+ fir_filter_ccf(int decimation,
+ const std::vector &taps);
+ ~fir_filter_ccf();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ gr_complex *d_taps;
+ };
+
+ /**************************************************************/
+
+ class FILTER_API fir_filter_ccc
+ {
+ public:
+ fir_filter_ccc(int decimation,
+ const std::vector &taps);
+ ~fir_filter_ccc();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+ unsigned int ntaps() const;
+
+ gr_complex filter(const gr_complex input[]);
+ void filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n);
+ void filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate);
+
+ private:
+ unsigned int d_ntaps;
+ gr_complex *d_taps;
+ };
+
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/include/filter/fir_filter_XXX.h.t b/gr-filter/include/filter/fir_filter_XXX.h.t
new file mode 100644
index 000000000..ef6b8bfc9
--- /dev/null
+++ b/gr-filter/include/filter/fir_filter_XXX.h.t
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator
+ {
+ public:
+
+ // gr::filter::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps
+ * \ingroup filter_blk
+ */
+ static FILTER_API sptr make(int decimation,
+ const std::vector<@TAP_TYPE@> &taps);
+
+ virtual void set_taps (const std::vector<@TAP_TYPE@> &taps) = 0;
+ virtual std::vector<@TAP_TYPE@> taps () const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/include/filter/fir_filter_fff.h b/gr-filter/include/filter/fir_filter_fff.h
deleted file mode 100644
index 5b6d19b34..000000000
--- a/gr-filter/include/filter/fir_filter_fff.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,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 FILTER_FIR_FILTER_FFF_H
-#define FILTER_FIR_FILTER_FFF_H
-
-#include
-#include
-
-namespace gr {
- namespace filter {
-
- class FILTER_API fir_filter_fff : virtual public gr_sync_decimator
- {
- public:
-
- // gr::filter::fir_filter_fff::sptr
- typedef boost::shared_ptr sptr;
-
- /*!
- * \brief FIR filter with float input, float output, and float taps
- * \ingroup filter_blk
- */
- static FILTER_API sptr make(int decimation,
- const std::vector &taps);
-
- virtual void set_taps (const std::vector &taps) = 0;
- virtual std::vector taps () const = 0;
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* FILTER_FIR_FILTER_FFF_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 2850b6925..784a3c109 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -17,6 +17,72 @@
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
+########################################################################
+# generate helper scripts to expand templated files
+########################################################################
+include(GrPython)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
+#!${PYTHON_EXECUTABLE}
+
+import sys, os, re
+sys.path.append('${GR_CORE_PYTHONPATH}')
+os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
+os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
+
+if __name__ == '__main__':
+ import build_utils
+ root, inp = sys.argv[1:3]
+ for sig in sys.argv[3:]:
+ name = re.sub ('X+', sig, root)
+ d = build_utils.standard_impl_dict2(name, sig, 'filter')
+ build_utils.expand_template(d, inp)
+")
+
+macro(expand_cc root)
+ #make a list of all the generated files
+ unset(expanded_files_cc)
+ unset(expanded_files_h)
+ foreach(sig ${ARGN})
+ string(REGEX REPLACE "X+" ${sig} name ${root})
+ list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc)
+ list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h)
+ endforeach(sig)
+
+ #create a command to generate the source files
+ add_custom_command(
+ OUTPUT ${expanded_files_cc}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.cc.t ${ARGN}
+ )
+
+ #create a command to generate the header file
+ add_custom_command(
+ OUTPUT ${expanded_files_h}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t
+ COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
+ ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py
+ ${root} ${root}.h.t ${ARGN}
+ )
+
+ #make source files depends on headers to force generation
+ set_source_files_properties(${expanded_files_cc}
+ PROPERTIES OBJECT_DEPENDS "${expanded_files_h}"
+ )
+
+ #install rules for the generated cc files
+ list(APPEND generated_sources ${expanded_files_cc})
+ list(APPEND generated_headers ${expanded_files_h})
+endmacro(expand_cc)
+
+########################################################################
+# Invoke macro to generate various sources
+########################################################################
+expand_cc(fir_filter_XXX_impl fff ccf ccc)
+
+
########################################################################
# Setup the include and linker paths
########################################################################
@@ -39,7 +105,8 @@ link_directories(${FFTW3F_LIBRARY_DIRS})
# Setup library
########################################################################
list(APPEND filter_sources
- fir_filter_fff_impl.cc
+ fir_filter.cc
+ ${generated_sources}
)
list(APPEND filter_libs
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
new file mode 100644
index 000000000..5f0e0912d
--- /dev/null
+++ b/gr-filter/lib/fir_filter.cc
@@ -0,0 +1,268 @@
+/* -*- 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.
+ */
+
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+ namespace impl {
+
+ fir_filter_fff::fir_filter_fff(int decimation,
+ const std::vector &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_fff::~fir_filter_fff()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_fff::set_taps(const std::vector &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_float(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = taps[i];
+ }
+ }
+
+ std::vector
+ fir_filter_fff::taps() const
+ {
+ std::vector t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i]);
+ return t;
+ }
+
+ unsigned int
+ fir_filter_fff::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ float
+ fir_filter_fff::filter(const float input[])
+ {
+ float output;
+ volk_32f_x2_dot_prod_32f_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_fff::filterN(float output[],
+ const float input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_fff::filterNdec(float output[],
+ const float input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_ccf::fir_filter_ccf(int decimation,
+ const std::vector &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_ccf::~fir_filter_ccf()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_ccf::set_taps(const std::vector &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_complex(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = gr_complex(taps[i],0);
+ }
+ }
+
+ std::vector
+ fir_filter_ccf::taps() const
+ {
+ std::vector t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i].real());
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccf::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccf::filter(const gr_complex input[])
+ {
+ gr_complex output;
+ volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_ccf::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccf::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ /**************************************************************/
+
+ fir_filter_ccc::fir_filter_ccc(int decimation,
+ const std::vector &taps)
+ {
+ d_taps = NULL;
+ set_taps(taps);
+ }
+
+ fir_filter_ccc::~fir_filter_ccc()
+ {
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+ }
+
+ void
+ fir_filter_ccc::set_taps(const std::vector &taps)
+ {
+ // Free the taps if already allocated
+ if(d_taps != NULL) {
+ fft::free(d_taps);
+ d_taps = NULL;
+ }
+
+ d_ntaps = (int)taps.size();
+ d_taps = fft::malloc_complex(d_ntaps);
+ for(unsigned int i = 0; i < d_ntaps; i++) {
+ d_taps[i] = taps[i];
+ }
+ }
+
+ std::vector
+ fir_filter_ccc::taps() const
+ {
+ std::vector t;
+ for(unsigned int i = 0; i < d_ntaps; i++)
+ t.push_back(d_taps[i]);
+ return t;
+ }
+
+ unsigned int
+ fir_filter_ccc::ntaps() const
+ {
+ return d_ntaps;
+ }
+
+ gr_complex
+ fir_filter_ccc::filter(const gr_complex input[])
+ {
+ gr_complex output;
+ volk_32fc_x2_dot_prod_32fc_u(&output, input, d_taps, d_ntaps);
+ return output;
+ }
+
+ void
+ fir_filter_ccc::filterN(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n)
+ {
+ for(unsigned long i = 0; i < n; i++)
+ output[i] = filter(&input[i]);
+ }
+
+
+ void
+ fir_filter_ccc::filterNdec(gr_complex output[],
+ const gr_complex input[],
+ unsigned long n,
+ unsigned int decimate)
+ {
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++){
+ output[i] = filter(&input[j]);
+ j += decimate;
+ }
+ }
+
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fir_filter_XXX_impl.cc.t b/gr-filter/lib/fir_filter_XXX_impl.cc.t
new file mode 100644
index 000000000..70c3fba3f
--- /dev/null
+++ b/gr-filter/lib/fir_filter_XXX_impl.cc.t
@@ -0,0 +1,98 @@
+/* -*- 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "@IMPL_NAME@.h"
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ {
+ return gnuradio::get_initial_sptr(new @IMPL_NAME@
+ (decimation, taps));
+ }
+
+
+ @IMPL_NAME@::@IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps)
+ : gr_sync_decimator("fir_filter_fff",
+ gr_make_io_signature(1, 1, sizeof(@I_TYPE@)),
+ gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
+ decimation)
+ {
+ d_fir = new impl::@BASE_NAME@(decimation, taps);
+ d_updated = false;
+ set_history(d_fir->ntaps()+1);
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ delete d_fir;
+ }
+
+ void
+ @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps)
+ {
+ d_fir->set_taps(taps);
+ d_updated = true;
+ }
+
+ std::vector<@TAP_TYPE@>
+ @IMPL_NAME@::taps() const
+ {
+ return d_fir->taps();
+ }
+
+ int
+ @IMPL_NAME@::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0];
+ @O_TYPE@ *out = (@O_TYPE@*)output_items[0];
+
+ if (d_updated) {
+ set_history(d_fir->ntaps()+1);
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ if (decimation() == 1) {
+ d_fir->filterN(out, in, noutput_items);
+ }
+ else {
+ d_fir->filterNdec(out, in, noutput_items, decimation());
+ }
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
+
diff --git a/gr-filter/lib/fir_filter_XXX_impl.h.t b/gr-filter/lib/fir_filter_XXX_impl.h.t
new file mode 100644
index 000000000..a40c49bf2
--- /dev/null
+++ b/gr-filter/lib/fir_filter_XXX_impl.h.t
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
+ {
+ private:
+ impl::@BASE_NAME@ *d_fir;
+ bool d_updated;
+
+ public:
+ @IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps);
+
+ ~@IMPL_NAME@();
+
+ void set_taps(const std::vector<@TAP_TYPE@> &taps);
+ std::vector<@TAP_TYPE@> taps() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-filter/lib/fir_filter_fff_impl.cc b/gr-filter/lib/fir_filter_fff_impl.cc
deleted file mode 100644
index 15ccb4d07..000000000
--- a/gr-filter/lib/fir_filter_fff_impl.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "fir_filter_fff_impl.h"
-#include
-#include
-#include
-#include
-
-namespace gr {
- namespace filter {
-
- fir_filter_fff::sptr
- fir_filter_fff::make(int decimation, const std::vector &taps)
- {
- return gnuradio::get_initial_sptr(new fir_filter_fff_impl
- (decimation, taps));
- }
-
-
- fir_filter_fff_impl::fir_filter_fff_impl(int decimation,
- const std::vector &taps)
- : gr_sync_decimator("fir_filter_fff",
- gr_make_io_signature (1, 1, sizeof(float)),
- gr_make_io_signature (1, 1, sizeof(float)),
- decimation)
- {
- d_taps = NULL;
- set_taps(taps);
- d_updated = false;
- set_history(d_ntaps+1);
- }
-
- fir_filter_fff_impl::~fir_filter_fff_impl()
- {
- if(d_taps != NULL) {
- fft::free(d_taps);
- d_taps = NULL;
- }
- }
-
- void
- fir_filter_fff_impl::set_taps(const std::vector &taps)
- {
- // Free the taps if already allocated
- if(d_taps != NULL) {
- fft::free(d_taps);
- d_taps = NULL;
- }
-
- d_ntaps = (int)taps.size();
- d_taps = fft::malloc_float(d_ntaps);
- for(int i = 0; i < d_ntaps; i++) {
- d_taps[i] = taps[i];
- }
- d_updated = true;
- }
-
- std::vector
- fir_filter_fff_impl::taps() const
- {
- std::vector t;
- for(int i = 0; i < d_ntaps; i++)
- t.push_back(d_taps[i]);
- return t;
- }
-
- int
- fir_filter_fff_impl::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];
- float *out = (float*)output_items[0];
-
- if (d_updated) {
- set_history((unsigned int)d_ntaps+1);
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
- if (decimation() == 1) {
- for(int i = 0; i < noutput_items; i++) {
- volk_32f_x2_dot_prod_32f_u(&out[i], &in[i], d_taps, d_ntaps);
- }
- }
- else {
- int j = 0;
- for(int i = 0; i < noutput_items; i++) {
- volk_32f_x2_dot_prod_32f_u(&out[i], &in[j], d_taps, d_ntaps);
- j += decimation();
- }
- }
-
- return noutput_items;
- }
-
- } /* namespace filter */
-} /* namespace gr */
-
diff --git a/gr-filter/lib/fir_filter_fff_impl.h b/gr-filter/lib/fir_filter_fff_impl.h
deleted file mode 100644
index 962781466..000000000
--- a/gr-filter/lib/fir_filter_fff_impl.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2004,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 FILTER_FIR_FILTER_FFF_IMPL_H
-#define FILTER_FIR_FILTER_FFF_IMPL_H
-
-#include
-#include
-
-namespace gr {
- namespace filter {
-
- class FILTER_API fir_filter_fff_impl : public fir_filter_fff
- {
- private:
- float *d_taps;
- int d_ntaps;
- bool d_updated;
-
- public:
- fir_filter_fff_impl(int decimation,
- const std::vector &taps);
-
- ~fir_filter_fff_impl();
-
- void set_taps(const std::vector &taps);
- std::vector taps() const;
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* FILTER_FIR_FILTER_FFF_IMPL_H */
diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py
index 928f17aa3..2c88e7830 100755
--- a/gr-filter/python/qa_fir_filter.py
+++ b/gr-filter/python/qa_fir_filter.py
@@ -41,6 +41,28 @@ class test_filter(gr_unittest.TestCase):
result_data = dst.data()
self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5)
+ def test_fir_filter_ccf_001(self):
+ src_data = [1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = [0+0j, 0.5+0.5j, 1.5+1.5j, 2.5+2.5j]
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccf(1, [0.5, 0.5])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccc_001(self):
+ src_data = [1+1j, 2+2j, 3+3j, 4+4j]
+ expected_data = [0+0j, -0.5+1.5j, -1.5+4.5j, -2.5+7.5j]
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(1, [0.5+1j, 0.5+1j])
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
if __name__ == '__main__':
gr_unittest.run(test_filter, "test_filter.xml")
diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt
index 5dff9f631..3eee3a1ee 100644
--- a/gr-filter/swig/CMakeLists.txt
+++ b/gr-filter/swig/CMakeLists.txt
@@ -24,7 +24,7 @@ include(GrPython)
include(GrSwig)
set(GR_SWIG_INCLUDE_DIRS
- ${FILTER_INCLUDE_DIRS}
+ ${GR_FILTER_INCLUDE_DIRS}
${GNURADIO_CORE_SWIG_INCLUDE_DIRS}
${FFT_INCLUDE_DIRS}
${FFTW3F_INCLUDE_DIRS}
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index 55ee3c56c..28268528a 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -29,8 +29,14 @@
%{
#include "filter/fir_filter_fff.h"
+#include "filter/fir_filter_ccf.h"
+#include "filter/fir_filter_ccc.h"
%}
%include "filter/fir_filter_fff.h"
+%include "filter/fir_filter_ccf.h"
+%include "filter/fir_filter_ccc.h"
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc);
--
cgit
From 26531c2da601a1c21c50e3644350c604c27f8658 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 18:59:23 -0400
Subject: filter: fixed FIR filter taps and added complex FFT filter.
---
gr-filter/examples/fft_filter_ccc.py | 107 +++++++++
gr-filter/examples/fir_filter_ccc.py | 101 ++++++++
gr-filter/examples/fir_filter_fff.py | 7 +
gr-filter/include/filter/CMakeLists.txt | 2 +
gr-filter/include/filter/fft_filter.h | 105 +++++++++
gr-filter/include/filter/fft_filter_ccc.h | 67 ++++++
gr-filter/include/filter/fft_filter_fff.h | 88 +++++++
gr-filter/include/filter/fir_filter.h | 7 +-
gr-filter/lib/CMakeLists.txt | 2 +
gr-filter/lib/fft_filter.cc | 174 ++++++++++++++
gr-filter/lib/fft_filter_ccc_impl.cc | 119 ++++++++++
gr-filter/lib/fft_filter_ccc_impl.h | 61 +++++
gr-filter/lib/fft_filter_fff_impl.cc | 123 ++++++++++
gr-filter/lib/fft_filter_fff_impl.h | 88 +++++++
gr-filter/lib/fir_filter.cc | 14 +-
gr-filter/lib/fir_filter_XXX_impl.cc.t | 8 +-
gr-filter/lib/fir_filter_XXX_impl.h.t | 2 +-
gr-filter/python/qa_fft_filter.py | 380 ++++++++++++++++++++++++++++++
gr-filter/python/qa_fir_filter.py | 22 +-
gr-filter/swig/filter_swig.i | 3 +
20 files changed, 1463 insertions(+), 17 deletions(-)
create mode 100755 gr-filter/examples/fft_filter_ccc.py
create mode 100755 gr-filter/examples/fir_filter_ccc.py
create mode 100644 gr-filter/include/filter/fft_filter.h
create mode 100644 gr-filter/include/filter/fft_filter_ccc.h
create mode 100644 gr-filter/include/filter/fft_filter_fff.h
create mode 100644 gr-filter/lib/fft_filter.cc
create mode 100644 gr-filter/lib/fft_filter_ccc_impl.cc
create mode 100644 gr-filter/lib/fft_filter_ccc_impl.h
create mode 100644 gr-filter/lib/fft_filter_fff_impl.cc
create mode 100644 gr-filter/lib/fft_filter_fff_impl.h
create mode 100755 gr-filter/python/qa_fft_filter.py
diff --git a/gr-filter/examples/fft_filter_ccc.py b/gr-filter/examples/fft_filter_ccc.py
new file mode 100755
index 000000000..0844c88ef
--- /dev/null
+++ b/gr-filter/examples/fft_filter_ccc.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fft_filter_ccc(gr.top_block):
+ def __init__(self, N, fs, bw0, bw1, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw0 = bw0
+ self._bw1 = bw1
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = gr.firdes.complex_band_pass_2(1, self._fs,
+ self._bw0, self._bw1,
+ self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_gr_complex, self._nsamps)
+
+ self.filt0 = filter.fft_filter_ccc(self._decim, taps)
+ self.filt1 = gr.fft_filter_ccc(self._decim, taps)
+ #self.filt1 = filter.fft_filter_ccc(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_c()
+ self.vsnk_out = gr.vector_sink_c()
+ self.vsnk_gr = gr.vector_sink_c()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+ self.connect(self.head, self.filt1, self.vsnk_gr)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-S", "--start-pass", type="eng_float", default=1000,
+ help="Start of Passband [default=%default]")
+ parser.add_option("-E", "--end-pass", type="eng_float", default=2000,
+ help="End of Passband [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fft_filter_ccc(options.nsamples,
+ options.samplerate,
+ options.start_pass,
+ options.end_pass,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+ data_gr = scipy.array(put.vsnk_gr.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_gr, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+ s2.plot(data_gr.real, 'r--')
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fir_filter_ccc.py b/gr-filter/examples/fir_filter_ccc.py
new file mode 100755
index 000000000..57df868f7
--- /dev/null
+++ b/gr-filter/examples/fir_filter_ccc.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, filter
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+try:
+ import scipy
+except ImportError:
+ print "Error: could not import scipy (http://www.scipy.org/)"
+ sys.exit(1)
+
+try:
+ import pylab
+except ImportError:
+ print "Error: could not import pylab (http://matplotlib.sourceforge.net/)"
+ sys.exit(1)
+
+class example_fir_filter_ccc(gr.top_block):
+ def __init__(self, N, fs, bw, tw, atten, D):
+ gr.top_block.__init__(self)
+
+ self._nsamps = N
+ self._fs = fs
+ self._bw = bw
+ self._tw = tw
+ self._at = atten
+ self._decim = D
+ taps = gr.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at)
+ print "Num. Taps: ", len(taps)
+
+ self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1)
+ self.head = gr.head(gr.sizeof_gr_complex, self._nsamps)
+
+ self.filt0 = filter.fir_filter_ccc(self._decim, taps)
+ self.filt1 = gr.fir_filter_ccc(self._decim, taps)
+ #self.filt1 = filter.fft_filter_ccc(self._decim, taps)
+
+ self.vsnk_src = gr.vector_sink_c()
+ self.vsnk_out = gr.vector_sink_c()
+ self.vsnk_gr = gr.vector_sink_c()
+
+ self.connect(self.src, self.head, self.vsnk_src)
+ self.connect(self.head, self.filt0, self.vsnk_out)
+ self.connect(self.head, self.filt1, self.vsnk_gr)
+
+def main():
+ parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+ parser.add_option("-N", "--nsamples", type="int", default=10000,
+ help="Number of samples to process [default=%default]")
+ parser.add_option("-s", "--samplerate", type="eng_float", default=8000,
+ help="System sample rate [default=%default]")
+ parser.add_option("-B", "--bandwidth", type="eng_float", default=1000,
+ help="Filter bandwidth [default=%default]")
+ parser.add_option("-T", "--transition", type="eng_float", default=100,
+ help="Transition band [default=%default]")
+ parser.add_option("-A", "--attenuation", type="eng_float", default=80,
+ help="Stopband attenuation [default=%default]")
+ parser.add_option("-D", "--decimation", type="int", default=1,
+ help="Decmation factor [default=%default]")
+ (options, args) = parser.parse_args ()
+
+ put = example_fir_filter_ccc(options.nsamples,
+ options.samplerate,
+ options.bandwidth,
+ options.transition,
+ options.attenuation,
+ options.decimation)
+ put.run()
+
+ data_src = scipy.array(put.vsnk_src.data())
+ data_snk = scipy.array(put.vsnk_out.data())
+ data_gr = scipy.array(put.vsnk_gr.data())
+
+ # Plot the signals PSDs
+ nfft = 1024
+ f1 = pylab.figure(1, figsize=(12,10))
+ s1 = f1.add_subplot(1,1,1)
+ s1.psd(data_src, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+ s1.psd(data_gr, NFFT=nfft, noverlap=nfft/4,
+ Fs=options.samplerate)
+
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+ s2.plot(data_gr.real, 'r--')
+
+ pylab.show()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-filter/examples/fir_filter_fff.py b/gr-filter/examples/fir_filter_fff.py
index 538aded44..1ed889fcf 100755
--- a/gr-filter/examples/fir_filter_fff.py
+++ b/gr-filter/examples/fir_filter_fff.py
@@ -83,6 +83,13 @@ def main():
s1.psd(data_gr, NFFT=nfft, noverlap=nfft/4,
Fs=options.samplerate)
+
+ f2 = pylab.figure(2, figsize=(12,10))
+ s2 = f2.add_subplot(1,1,1)
+ s2.plot(data_src)
+ s2.plot(data_snk.real, 'g')
+ s2.plot(data_gr.real, 'r--')
+
pylab.show()
if __name__ == "__main__":
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index 4889312da..f96128805 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -76,7 +76,9 @@ add_custom_target(filter_generated_includes DEPENDS
install(FILES
api.h
fir_filter.h
+ fft_filter.h
${generated_includes}
+ fft_filter_ccc.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter
COMPONENT "fft_devel"
)
diff --git a/gr-filter/include/filter/fft_filter.h b/gr-filter/include/filter/fft_filter.h
new file mode 100644
index 000000000..fccea595f
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter.h
@@ -0,0 +1,105 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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_FILTER_FFT_FILTER_H
+#define INCLUDED_FILTER_FFT_FILTER_H
+
+#include
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ */
+ class FILTER_API fft_filter_ccc
+ {
+ private:
+ int d_ntaps;
+ int d_nsamples;
+ int d_fftsize; // fftsize = ntaps + nsamples - 1
+ int d_decimation;
+ fft::fft_complex *d_fwdfft; // forward "plan"
+ fft::fft_complex *d_invfft; // inverse "plan"
+ int d_nthreads; // number of FFTW threads to use
+ std::vector d_tail; // state carried between blocks for overlap-add
+ std::vector d_new_taps;
+ gr_complex *d_xformed_taps; // Fourier xformed taps
+
+ void compute_sizes(int ntaps);
+ int tailsize() const { return d_ntaps - 1; }
+
+ public:
+ /*!
+ * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate.
+ *
+ * This is the basic implementation for performing FFT filter for fast convolution
+ * in other blocks for complex vectors (such as gr_fft_filter_ccc).
+ *
+ * \param decimation The decimation rate of the filter (int)
+ * \param taps The filter taps (complex)
+ * \param nthreads The number of threads for the FFT to use (int)
+ */
+ fft_filter_ccc(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccc();
+
+ /*!
+ * \brief Set new taps for the filter.
+ *
+ * Sets new taps and resets the class properties to handle different sizes
+ * \param taps The filter taps (complex)
+ */
+ int set_taps(const std::vector &taps);
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ /*!
+ * \brief Perform the filter operation
+ *
+ * \param nitems The number of items to produce
+ * \param input The input vector to be filtered
+ * \param output The result of the filter operation
+ */
+ int filter(int nitems, const gr_complex *input, gr_complex *output);
+ };
+
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_H */
diff --git a/gr-filter/include/filter/fft_filter_ccc.h b/gr-filter/include/filter/fft_filter_ccc.h
new file mode 100644
index 000000000..a309ffc22
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter_ccc.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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_FILTER_FFT_FILTER_CCC_H
+#define INCLUDED_FILTER_FFT_FILTER_CCC_H
+
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_ccc : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::fft_filter::sptr
+ typedef boost::shared_ptr sptr;
+
+ /*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ *
+ * \param decimation >= 1
+ * \param taps complex filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ static FILTER_API sptr make(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
+
+ virtual void set_taps(const std::vector &taps) = 0;
+ virtual std::vector taps() const = 0;
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ virtual void set_nthreads(int n) = 0;
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ virtual int nthreads() const = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_H */
diff --git a/gr-filter/include/filter/fft_filter_fff.h b/gr-filter/include/filter/fft_filter_fff.h
new file mode 100644
index 000000000..309a55135
--- /dev/null
+++ b/gr-filter/include/filter/fft_filter_fff.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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_GR_FFT_FILTER_FFF_H
+#define INCLUDED_GR_FFT_FILTER_FFF_H
+
+#include
+#include
+
+class gr_fft_filter_fff;
+typedef boost::shared_ptr gr_fft_filter_fff_sptr;
+GR_CORE_API gr_fft_filter_fff_sptr
+gr_make_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads=1);
+
+class gri_fft_filter_fff_generic;
+//class gri_fft_filter_fff_sse;
+
+/*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ */
+class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator
+{
+ private:
+ friend GR_CORE_API gr_fft_filter_fff_sptr
+ gr_make_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads);
+
+ int d_nsamples;
+ bool d_updated;
+#if 1 // don't enable the sse version until handling it is worked out
+ gri_fft_filter_fff_generic *d_filter;
+#else
+ gri_fft_filter_fff_sse *d_filter;
+#endif
+ std::vector d_new_taps;
+
+ /*!
+ * Construct a FFT filter with the given taps
+ *
+ * \param decimation >= 1
+ * \param taps float filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ gr_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads=1);
+
+ public:
+ ~gr_fft_filter_fff ();
+
+ void set_taps (const std::vector &taps);
+ std::vector taps () const;
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
index c307fea46..525532fe6 100644
--- a/gr-filter/include/filter/fir_filter.h
+++ b/gr-filter/include/filter/fir_filter.h
@@ -20,13 +20,16 @@
* Boston, MA 02110-1301, USA.
*/
+#ifndef INCLUDED_FILTER_FIR_FILTER_H
+#define INCLUDED_FILTER_FIR_FILTER_H
+
#include
#include
#include
namespace gr {
namespace filter {
- namespace impl {
+ namespace kernel {
class FILTER_API fir_filter_fff
{
@@ -110,3 +113,5 @@ namespace gr {
} /* namespace impl */
} /* namespace filter */
} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FIR_FILTER_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index 784a3c109..aa03c4615 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -106,7 +106,9 @@ link_directories(${FFTW3F_LIBRARY_DIRS})
########################################################################
list(APPEND filter_sources
fir_filter.cc
+ fft_filter.cc
${generated_sources}
+ fft_filter_ccc_impl.cc
)
list(APPEND filter_libs
diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc
new file mode 100644
index 000000000..86b2a2fdb
--- /dev/null
+++ b/gr-filter/lib/fft_filter.cc
@@ -0,0 +1,174 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 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
+#include
+#include
+
+namespace gr {
+ namespace filter {
+ namespace kernel {
+
+ #define VERBOSE 0
+
+ fft_filter_ccc::fft_filter_ccc(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0),
+ d_invfft(0), d_nthreads(nthreads)
+ {
+ set_taps(taps);
+ }
+
+ fft_filter_ccc::~fft_filter_ccc()
+ {
+ delete d_fwdfft;
+ delete d_invfft;
+ fft::free(d_xformed_taps);
+ }
+
+ /*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+ int
+ fft_filter_ccc::set_taps(const std::vector &taps)
+ {
+ int i = 0;
+ compute_sizes(taps.size());
+
+ d_tail.resize(tailsize());
+ for(i = 0; i < tailsize(); i++)
+ d_tail[i] = 0;
+
+ gr_complex *in = d_fwdfft->get_inbuf();
+ gr_complex *out = d_fwdfft->get_outbuf();
+
+ float scale = 1.0 / d_fftsize;
+
+ // Compute forward xform of taps.
+ // Copy taps into first ntaps slots, then pad with zeros
+ for(i = 0; i < d_ntaps; i++)
+ in[i] = taps[i] * scale;
+
+ for(; i < d_fftsize; i++)
+ in[i] = 0;
+
+ d_fwdfft->execute(); // do the xform
+
+ // now copy output to d_xformed_taps
+ for(i = 0; i < d_fftsize; i++)
+ d_xformed_taps[i] = out[i];
+
+ return d_nsamples;
+ }
+
+ // determine and set d_ntaps, d_nsamples, d_fftsize
+ void
+ fft_filter_ccc::compute_sizes(int ntaps)
+ {
+ int old_fftsize = d_fftsize;
+ d_ntaps = ntaps;
+ d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0))));
+ d_nsamples = d_fftsize - d_ntaps + 1;
+
+ if(VERBOSE) {
+ std::cerr << "fft_filter_ccc: ntaps = " << d_ntaps
+ << " fftsize = " << d_fftsize
+ << " nsamples = " << d_nsamples << std::endl;
+ }
+
+ // compute new plans
+ if(d_fftsize != old_fftsize) {
+ delete d_fwdfft;
+ delete d_invfft;
+ d_fwdfft = new fft::fft_complex(d_fftsize, true, d_nthreads);
+ d_invfft = new fft::fft_complex(d_fftsize, false, d_nthreads);
+ d_xformed_taps = fft::malloc_complex(d_fftsize);
+ }
+ }
+
+ void
+ fft_filter_ccc::set_nthreads(int n)
+ {
+ d_nthreads = n;
+ if(d_fwdfft)
+ d_fwdfft->set_nthreads(n);
+ if(d_invfft)
+ d_invfft->set_nthreads(n);
+ }
+
+ int
+ fft_filter_ccc::nthreads() const
+ {
+ return d_nthreads;
+ }
+
+ int
+ fft_filter_ccc::filter (int nitems, const gr_complex *input, gr_complex *output)
+ {
+ int dec_ctr = 0;
+ int j = 0;
+ int ninput_items = nitems * d_decimation;
+
+ for(int i = 0; i < ninput_items; i += d_nsamples) {
+ memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex));
+
+ for(j = d_nsamples; j < d_fftsize; j++)
+ d_fwdfft->get_inbuf()[j] = 0;
+
+ d_fwdfft->execute(); // compute fwd xform
+
+ gr_complex *a = d_fwdfft->get_outbuf();
+ gr_complex *b = d_xformed_taps;
+ gr_complex *c = d_invfft->get_inbuf();
+
+ volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize);
+
+ d_invfft->execute(); // compute inv xform
+
+ // add in the overlapping tail
+
+ for(j = 0; j < tailsize(); j++)
+ d_invfft->get_outbuf()[j] += d_tail[j];
+
+ // copy nsamples to output
+ j = dec_ctr;
+ while(j < d_nsamples) {
+ *output++ = d_invfft->get_outbuf()[j];
+ j += d_decimation;
+ }
+ dec_ctr = (j - d_nsamples);
+
+ // stash the tail
+ memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+ tailsize() * sizeof(gr_complex));
+ }
+
+ return nitems;
+ }
+ } /* namespace impl */
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_ccc_impl.cc b/gr-filter/lib/fft_filter_ccc_impl.cc
new file mode 100644
index 000000000..2721f128e
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccc_impl.cc
@@ -0,0 +1,119 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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_filter_ccc_impl.h"
+#include
+
+#include
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ fft_filter_ccc::sptr fft_filter_ccc::make(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ {
+ return gnuradio::get_initial_sptr(new fft_filter_ccc_impl
+ (decimation, taps, nthreads));
+ }
+
+ fft_filter_ccc_impl::fft_filter_ccc_impl(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ : gr_sync_decimator("fft_filter_ccc",
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ decimation),
+ d_updated(false)
+ {
+ set_history(1);
+
+ d_filter = new kernel::fft_filter_ccc(decimation, taps, nthreads);
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+ }
+
+ fft_filter_ccc_impl::~fft_filter_ccc_impl()
+ {
+ delete d_filter;
+ }
+
+ void
+ fft_filter_ccc_impl::set_taps(const std::vector &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector
+ fft_filter_ccc_impl::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ fft_filter_ccc_impl::set_nthreads(int n)
+ {
+ if(d_filter)
+ d_filter->set_nthreads(n);
+ }
+
+ int
+ fft_filter_ccc_impl::nthreads() const
+ {
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+ }
+
+ int
+ fft_filter_ccc_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];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ if (d_updated){
+ d_nsamples = d_filter->set_taps(d_new_taps);
+ d_updated = false;
+ set_output_multiple(d_nsamples);
+ return 0; // output multiple may have changed
+ }
+
+ d_filter->filter(noutput_items, in, out);
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_ccc_impl.h b/gr-filter/lib/fft_filter_ccc_impl.h
new file mode 100644
index 000000000..2d8d61c5e
--- /dev/null
+++ b/gr-filter/lib/fft_filter_ccc_impl.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,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_FILTER_FFT_FILTER_CCC_IMPL_H
+#define INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H
+
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_ccc_impl : public fft_filter_ccc
+ {
+ private:
+ int d_nsamples;
+ bool d_updated;
+ kernel::fft_filter_ccc *d_filter;
+ std::vector d_new_taps;
+
+ public:
+ fft_filter_ccc_impl(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
+
+ ~fft_filter_ccc_impl();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+
+ void set_nthreads(int n);
+ int nthreads() const;
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H */
diff --git a/gr-filter/lib/fft_filter_fff_impl.cc b/gr-filter/lib/fft_filter_fff_impl.cc
new file mode 100644
index 000000000..a09feb7f1
--- /dev/null
+++ b/gr-filter/lib/fft_filter_fff_impl.cc
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005,2010 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
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation,
+ const std::vector &taps,
+ int nthreads)
+{
+ return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps, nthreads));
+}
+
+
+gr_fft_filter_fff::gr_fft_filter_fff (int decimation,
+ const std::vector &taps,
+ int nthreads)
+ : gr_sync_decimator ("fft_filter_fff",
+ gr_make_io_signature (1, 1, sizeof (float)),
+ gr_make_io_signature (1, 1, sizeof (float)),
+ decimation),
+ d_updated(false)
+{
+ set_history(1);
+
+#if 1 // don't enable the sse version until handling it is worked out
+ d_filter = new gri_fft_filter_fff_generic(decimation, taps, nthreads);
+#else
+ d_filter = new gri_fft_filter_fff_sse(decimation, taps);
+#endif
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+}
+
+gr_fft_filter_fff::~gr_fft_filter_fff ()
+{
+ delete d_filter;
+}
+
+void
+gr_fft_filter_fff::set_taps (const std::vector &taps)
+{
+ d_new_taps = taps;
+ d_updated = true;
+}
+
+std::vector
+gr_fft_filter_fff::taps () const
+{
+ return d_new_taps;
+}
+
+void
+gr_fft_filter_fff::set_nthreads(int n)
+{
+ if(d_filter)
+ d_filter->set_nthreads(n);
+}
+
+int
+gr_fft_filter_fff::nthreads() const
+{
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+}
+
+int
+gr_fft_filter_fff::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];
+ float *out = (float *) output_items[0];
+
+ if (d_updated){
+ d_nsamples = d_filter->set_taps(d_new_taps);
+ d_updated = false;
+ set_output_multiple(d_nsamples);
+ return 0; // output multiple may have changed
+ }
+
+ assert(noutput_items % d_nsamples == 0);
+
+ d_filter->filter(noutput_items, in, out);
+
+ //assert((out - (float *) output_items[0]) == noutput_items);
+
+ return noutput_items;
+}
diff --git a/gr-filter/lib/fft_filter_fff_impl.h b/gr-filter/lib/fft_filter_fff_impl.h
new file mode 100644
index 000000000..309a55135
--- /dev/null
+++ b/gr-filter/lib/fft_filter_fff_impl.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 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_GR_FFT_FILTER_FFF_H
+#define INCLUDED_GR_FFT_FILTER_FFF_H
+
+#include
+#include
+
+class gr_fft_filter_fff;
+typedef boost::shared_ptr gr_fft_filter_fff_sptr;
+GR_CORE_API gr_fft_filter_fff_sptr
+gr_make_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads=1);
+
+class gri_fft_filter_fff_generic;
+//class gri_fft_filter_fff_sse;
+
+/*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ */
+class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator
+{
+ private:
+ friend GR_CORE_API gr_fft_filter_fff_sptr
+ gr_make_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads);
+
+ int d_nsamples;
+ bool d_updated;
+#if 1 // don't enable the sse version until handling it is worked out
+ gri_fft_filter_fff_generic *d_filter;
+#else
+ gri_fft_filter_fff_sse *d_filter;
+#endif
+ std::vector d_new_taps;
+
+ /*!
+ * Construct a FFT filter with the given taps
+ *
+ * \param decimation >= 1
+ * \param taps float filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ gr_fft_filter_fff (int decimation, const std::vector &taps,
+ int nthreads=1);
+
+ public:
+ ~gr_fft_filter_fff ();
+
+ void set_taps (const std::vector &taps);
+ std::vector taps () const;
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
index 5f0e0912d..321f6981e 100644
--- a/gr-filter/lib/fir_filter.cc
+++ b/gr-filter/lib/fir_filter.cc
@@ -26,7 +26,7 @@
namespace gr {
namespace filter {
- namespace impl {
+ namespace kernel {
fir_filter_fff::fir_filter_fff(int decimation,
const std::vector &taps)
@@ -55,7 +55,7 @@ namespace gr {
d_ntaps = (int)taps.size();
d_taps = fft::malloc_float(d_ntaps);
for(unsigned int i = 0; i < d_ntaps; i++) {
- d_taps[i] = taps[i];
+ d_taps[d_ntaps-i-1] = taps[i];
}
}
@@ -64,7 +64,7 @@ namespace gr {
{
std::vector t;
for(unsigned int i = 0; i < d_ntaps; i++)
- t.push_back(d_taps[i]);
+ t.push_back(d_taps[d_ntaps-i-1]);
return t;
}
@@ -134,7 +134,7 @@ namespace gr {
d_ntaps = (int)taps.size();
d_taps = fft::malloc_complex(d_ntaps);
for(unsigned int i = 0; i < d_ntaps; i++) {
- d_taps[i] = gr_complex(taps[i],0);
+ d_taps[d_ntaps-i-1] = gr_complex(taps[i],0);
}
}
@@ -143,7 +143,7 @@ namespace gr {
{
std::vector t;
for(unsigned int i = 0; i < d_ntaps; i++)
- t.push_back(d_taps[i].real());
+ t.push_back(d_taps[d_ntaps-i-1].real());
return t;
}
@@ -213,7 +213,7 @@ namespace gr {
d_ntaps = (int)taps.size();
d_taps = fft::malloc_complex(d_ntaps);
for(unsigned int i = 0; i < d_ntaps; i++) {
- d_taps[i] = taps[i];
+ d_taps[d_ntaps-i-1] = taps[i];
}
}
@@ -222,7 +222,7 @@ namespace gr {
{
std::vector t;
for(unsigned int i = 0; i < d_ntaps; i++)
- t.push_back(d_taps[i]);
+ t.push_back(d_taps[d_ntaps-i-1]);
return t;
}
diff --git a/gr-filter/lib/fir_filter_XXX_impl.cc.t b/gr-filter/lib/fir_filter_XXX_impl.cc.t
index 70c3fba3f..c3637042d 100644
--- a/gr-filter/lib/fir_filter_XXX_impl.cc.t
+++ b/gr-filter/lib/fir_filter_XXX_impl.cc.t
@@ -26,8 +26,6 @@
#include "@IMPL_NAME@.h"
#include
-#include
-#include
namespace gr {
namespace filter {
@@ -46,9 +44,9 @@ namespace gr {
gr_make_io_signature(1, 1, sizeof(@O_TYPE@)),
decimation)
{
- d_fir = new impl::@BASE_NAME@(decimation, taps);
+ d_fir = new kernel::@BASE_NAME@(decimation, taps);
d_updated = false;
- set_history(d_fir->ntaps()+1);
+ set_history(d_fir->ntaps());
}
@IMPL_NAME@::~@IMPL_NAME@()
@@ -78,7 +76,7 @@ namespace gr {
@O_TYPE@ *out = (@O_TYPE@*)output_items[0];
if (d_updated) {
- set_history(d_fir->ntaps()+1);
+ set_history(d_fir->ntaps());
d_updated = false;
return 0; // history requirements may have changed.
}
diff --git a/gr-filter/lib/fir_filter_XXX_impl.h.t b/gr-filter/lib/fir_filter_XXX_impl.h.t
index a40c49bf2..d5bf7104d 100644
--- a/gr-filter/lib/fir_filter_XXX_impl.h.t
+++ b/gr-filter/lib/fir_filter_XXX_impl.h.t
@@ -35,7 +35,7 @@ namespace gr {
class FILTER_API @IMPL_NAME@ : public @BASE_NAME@
{
private:
- impl::@BASE_NAME@ *d_fir;
+ kernel::@BASE_NAME@ *d_fir;
bool d_updated;
public:
diff --git a/gr-filter/python/qa_fft_filter.py b/gr-filter/python/qa_fft_filter.py
new file mode 100755
index 000000000..33d3d870b
--- /dev/null
+++ b/gr-filter/python/qa_fft_filter.py
@@ -0,0 +1,380 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2005,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
+import filter_swig as filter
+import sys
+import random
+
+def make_random_complex_tuple(L):
+ result = []
+ for x in range(L):
+ result.append(complex(random.uniform(-1000,1000),
+ random.uniform(-1000,1000)))
+ return tuple(result)
+
+def make_random_float_tuple(L):
+ result = []
+ for x in range(L):
+ result.append(float(int(random.uniform(-1000,1000))))
+ return tuple(result)
+
+
+def reference_filter_ccc(dec, taps, input):
+ """
+ compute result using conventional fir filter
+ """
+ tb = gr.top_block()
+ #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input)
+ src = gr.vector_source_c(input)
+ op = filter.fir_filter_ccc(dec, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ return dst.data()
+
+def reference_filter_fff(dec, taps, input):
+ """
+ compute result using conventional fir filter
+ """
+ tb = gr.top_block()
+ #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input)
+ src = gr.vector_source_f(input)
+ op = filter.fir_filter_fff(dec, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ return dst.data()
+
+
+def print_complex(x):
+ for i in x:
+ i = complex(i)
+ sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag))
+ sys.stdout.write('\n')
+
+
+class test_fft_filter(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_ccc_001(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (1,)
+ expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = gr.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_ccc_002(self):
+ # Test nthreads
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ nthreads = 2
+ expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = gr.fft_filter_ccc(1, taps, nthreads)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def test_ccc_003(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_c(src_data)
+ op = gr.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_ccc_004(self):
+ random.seed(0)
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(1, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ del tb
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_ccc_005(self):
+ random.seed(0)
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(dec, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = gr.fft_filter_ccc(dec, taps)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ del tb
+ result_data = dst.data()
+
+ self.assert_fft_ok2(expected_result, result_data)
+
+ def test_ccc_006(self):
+ # Test decimating with nthreads=2
+ random.seed(0)
+ nthreads = 2
+ for i in xrange(25):
+ # sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_complex_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+ expected_result = reference_filter_ccc(dec, taps, src_data)
+
+ src = gr.vector_source_c(src_data)
+ op = filter.fft_filter_ccc(dec, taps, nthreads)
+ dst = gr.vector_sink_c()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ del tb
+ result_data = dst.data()
+
+ self.assert_fft_ok2(expected_result, result_data)
+
+ # ----------------------------------------------------------------
+ # test _fff version
+ # ----------------------------------------------------------------
+
+ def test_fff_001(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (1,)
+ expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+
+ def test_fff_002(self):
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ #print 'expected:', expected_result
+ #print 'results: ', result_data
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def test_fff_003(self):
+ # Test 02 with nthreads
+ tb = gr.top_block()
+ src_data = (0,1,2,3,4,5,6,7)
+ taps = (2,)
+ nthreads = 2
+ expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(1, taps, nthreads)
+ dst = gr.vector_sink_f()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+ self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5)
+
+ def xtest_fff_004(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4096
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(1, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ #print "src_len =", src_len, " ntaps =", ntaps
+ try:
+ self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0)
+ except:
+ expected = open('expected', 'w')
+ for x in expected_result:
+ expected.write(`x` + '\n')
+ actual = open('actual', 'w')
+ for x in result_data:
+ actual.write(`x` + '\n')
+ raise
+
+ def xtest_fff_005(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 1000))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(1, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(1, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0)
+
+ def xtest_fff_006(self):
+ random.seed(0)
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(dec, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(dec, taps)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data)
+
+ def xtest_fff_007(self):
+ # test decimation with nthreads
+ random.seed(0)
+ nthreads = 2
+ for i in xrange(25):
+ sys.stderr.write("\n>>> Loop = %d\n" % (i,))
+ dec = i + 1
+ src_len = 4*1024
+ src_data = make_random_float_tuple(src_len)
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+ expected_result = reference_filter_fff(dec, taps, src_data)
+
+ src = gr.vector_source_f(src_data)
+ op = gr.fft_filter_fff(dec, taps, nthreads)
+ dst = gr.vector_sink_f()
+ tb = gr.top_block()
+ tb.connect(src, op, dst)
+ tb.run()
+ result_data = dst.data()
+
+ self.assert_fft_float_ok2(expected_result, result_data)
+
+ def test_fff_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_float_tuple(ntaps)
+
+ op = gr.fft_filter_fff(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertEqual(taps, result_data)
+
+ def test_ccc_get0(self):
+ random.seed(0)
+ for i in xrange(25):
+ ntaps = int(random.uniform(2, 100))
+ taps = make_random_complex_tuple(ntaps)
+
+ op = gr.fft_filter_ccc(1, taps)
+ result_data = op.taps()
+ #print result_data
+
+ self.assertComplexTuplesAlmostEqual(taps, result_data, 4)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_fft_filter, "test_fft_filter.xml")
+
diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py
index 2c88e7830..f0f08afca 100755
--- a/gr-filter/python/qa_fir_filter.py
+++ b/gr-filter/python/qa_fir_filter.py
@@ -32,7 +32,7 @@ class test_filter(gr_unittest.TestCase):
def test_fir_filter_fff_001(self):
src_data = [1, 2, 3, 4]
- expected_data = [0, 0.5, 1.5, 2.5]
+ expected_data = [0.5, 1.5, 2.5, 3.5]
src = gr.vector_source_f(src_data)
op = filter.fir_filter_fff(1, [0.5, 0.5])
dst = gr.vector_sink_f()
@@ -43,7 +43,7 @@ class test_filter(gr_unittest.TestCase):
def test_fir_filter_ccf_001(self):
src_data = [1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = [0+0j, 0.5+0.5j, 1.5+1.5j, 2.5+2.5j]
+ expected_data = [0.5+0.5j, 1.5+1.5j, 2.5+2.5j, 3.5+3.5j]
src = gr.vector_source_c(src_data)
op = filter.fir_filter_ccf(1, [0.5, 0.5])
dst = gr.vector_sink_c()
@@ -54,7 +54,7 @@ class test_filter(gr_unittest.TestCase):
def test_fir_filter_ccc_001(self):
src_data = [1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = [0+0j, -0.5+1.5j, -1.5+4.5j, -2.5+7.5j]
+ expected_data = [-0.5+1.5j, -1.5+4.5j, -2.5+7.5j, -3.5+10.5j]
src = gr.vector_source_c(src_data)
op = filter.fir_filter_ccc(1, [0.5+1j, 0.5+1j])
dst = gr.vector_sink_c()
@@ -63,6 +63,22 @@ class test_filter(gr_unittest.TestCase):
result_data = dst.data()
self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
+ def test_fir_filter_ccc_002(self):
+ src_data = 10*[1+1j, 2+2j, 3+3j, 4+4j]
+
+ # results derived from original gr.fir_filter_ccc
+ expected_data = ((7.537424837948042e-20+7.537424837948042e-20j), (9.131923434324563e-05+9.131923434324563e-05j), (0.0003317668742965907+0.0003317668742965907j), (0.0007230418268591166+0.0007230418268591166j), (0.0012087896466255188+0.0012087896466255188j), (0.0013292605290189385+0.0013292605290189385j), (0.001120875240303576+0.001120875240303576j), (0.000744672492146492+0.000744672492146492j), (0.000429437990533188+0.000429437990533188j), (2.283908543176949e-05+2.283908543176949e-05j), (-0.0002245186478830874-0.0002245186478830874j), (-0.0001157080550910905-0.0001157080550910905j), (0.00041409023106098175+0.00041409023106098175j), (0.0009017843985930085+0.0009017843985930085j), (0.0012520025484263897+0.0012520025484263897j), (0.0014116164529696107+0.0014116164529696107j), (0.001393353333696723+0.001393353333696723j), (0.000912194955162704+0.000912194955162704j), (0.00022649182938039303+0.00022649182938039303j), (-0.00031363096786662936-0.00031363096786662936j), (-0.0003966730728279799-0.0003966730728279799j), (-0.00023757052258588374-0.00023757052258588374j), (0.00021952332463115454+0.00021952332463115454j), (0.0009092430118471384+0.0009092430118471384j), (0.001662317430600524+0.001662317430600524j), (0.0019024648936465383+0.0019024648936465383j), (0.0015955769922584295+0.0015955769922584295j), (0.0009144138311967254+0.0009144138311967254j), (0.0001872836146503687+0.0001872836146503687j), (-0.000581968342885375-0.000581968342885375j), (-0.0009886166080832481-0.0009886166080832481j), (-0.0007480768254026771-0.0007480768254026771j), (0.00018211957649327815+0.00018211957649327815j), (0.0012042406015098095+0.0012042406015098095j), (0.0020200139842927456+0.0020200139842927456j), (0.0023816542234271765+0.0023816542234271765j), (0.002195809967815876+0.002195809967815876j), (0.0012113333214074373+0.0012113333214074373j), (-0.00014088614261709154-0.00014088614261709154j), (-0.0012574587017297745-0.0012574587017297745j))
+
+ taps = gr.firdes.low_pass(1, 1, 0.1, 0.01)
+ src = gr.vector_source_c(src_data)
+ op = filter.fir_filter_ccc(1, taps)
+ dst = gr.vector_sink_c()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
+
if __name__ == '__main__':
gr_unittest.run(test_filter, "test_filter.xml")
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index 28268528a..94ad9cd64 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -31,12 +31,15 @@
#include "filter/fir_filter_fff.h"
#include "filter/fir_filter_ccf.h"
#include "filter/fir_filter_ccc.h"
+#include "filter/fft_filter_ccc.h"
%}
%include "filter/fir_filter_fff.h"
%include "filter/fir_filter_ccf.h"
%include "filter/fir_filter_ccc.h"
+%include "filter/fft_filter_ccc.h"
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc);
--
cgit
From b63e3b8a6923cf358d42064dca16d262a33c2918 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 19:59:43 -0400
Subject: filter: adding fff version of FFT filter.
---
gr-filter/include/filter/fft_filter.h | 70 ++++++++++-
gr-filter/include/filter/fft_filter_ccc.h | 2 +-
gr-filter/include/filter/fft_filter_fff.h | 95 ++++++---------
gr-filter/include/filter/fir_filter.h | 2 +-
gr-filter/lib/CMakeLists.txt | 1 +
gr-filter/lib/fft_filter.cc | 145 ++++++++++++++++++++++-
gr-filter/lib/fft_filter_ccc_impl.h | 10 +-
gr-filter/lib/fft_filter_fff_impl.cc | 187 +++++++++++++++---------------
gr-filter/lib/fft_filter_fff_impl.h | 109 +++++++----------
gr-filter/lib/fir_filter.cc | 2 +-
gr-filter/python/qa_fft_filter.py | 18 +--
gr-filter/swig/filter_swig.i | 3 +
12 files changed, 402 insertions(+), 242 deletions(-)
diff --git a/gr-filter/include/filter/fft_filter.h b/gr-filter/include/filter/fft_filter.h
index fccea595f..8c7d6cf78 100644
--- a/gr-filter/include/filter/fft_filter.h
+++ b/gr-filter/include/filter/fft_filter.h
@@ -31,6 +31,72 @@
namespace gr {
namespace filter {
namespace kernel {
+ /*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ */
+ class FILTER_API fft_filter_fff
+ {
+ private:
+ int d_ntaps;
+ int d_nsamples;
+ int d_fftsize; // fftsize = ntaps + nsamples - 1
+ int d_decimation;
+ fft::fft_real_fwd *d_fwdfft; // forward "plan"
+ fft::fft_real_rev *d_invfft; // inverse "plan"
+ int d_nthreads; // number of FFTW threads to use
+ std::vector d_tail; // state carried between blocks for overlap-add
+ std::vector d_new_taps;
+ gr_complex *d_xformed_taps; // Fourier xformed taps
+
+ void compute_sizes(int ntaps);
+ int tailsize() const { return d_ntaps - 1; }
+
+ public:
+ /*!
+ * \brief Construct an FFT filter for float vectors with the given taps and decimation rate.
+ *
+ * This is the basic implementation for performing FFT filter for fast convolution
+ * in other blocks for complex vectors (such as fft_filter_ccc).
+ *
+ * \param decimation The decimation rate of the filter (int)
+ * \param taps The filter taps (complex)
+ * \param nthreads The number of threads for the FFT to use (int)
+ */
+ fft_filter_fff(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
+
+ ~fft_filter_fff();
+
+ /*!
+ * \brief Set new taps for the filter.
+ *
+ * Sets new taps and resets the class properties to handle different sizes
+ * \param taps The filter taps (complex)
+ */
+ int set_taps(const std::vector &taps);
+
+ /*!
+ * \brief Set number of threads to use.
+ */
+ void set_nthreads(int n);
+
+ /*!
+ * \brief Get number of threads being used.
+ */
+ int nthreads() const;
+
+ /*!
+ * \brief Perform the filter operation
+ *
+ * \param nitems The number of items to produce
+ * \param input The input vector to be filtered
+ * \param output The result of the filter operation
+ */
+ int filter(int nitems, const float *input, float *output);
+ };
+
/*!
* \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
@@ -58,7 +124,7 @@ namespace gr {
* \brief Construct an FFT filter for complex vectors with the given taps and decimation rate.
*
* This is the basic implementation for performing FFT filter for fast convolution
- * in other blocks for complex vectors (such as gr_fft_filter_ccc).
+ * in other blocks for complex vectors (such as fft_filter_ccc).
*
* \param decimation The decimation rate of the filter (int)
* \param taps The filter taps (complex)
@@ -98,7 +164,7 @@ namespace gr {
int filter(int nitems, const gr_complex *input, gr_complex *output);
};
- } /* namespace impl */
+ } /* namespace kernel */
} /* namespace filter */
} /* namespace gr */
diff --git a/gr-filter/include/filter/fft_filter_ccc.h b/gr-filter/include/filter/fft_filter_ccc.h
index a309ffc22..29fd54713 100644
--- a/gr-filter/include/filter/fft_filter_ccc.h
+++ b/gr-filter/include/filter/fft_filter_ccc.h
@@ -32,7 +32,7 @@ namespace gr {
class FILTER_API fft_filter_ccc : virtual public gr_sync_decimator
{
public:
- // gr::filter::fft_filter::sptr
+ // gr::filter::fft_filter_ccc::sptr
typedef boost::shared_ptr sptr;
/*!
diff --git a/gr-filter/include/filter/fft_filter_fff.h b/gr-filter/include/filter/fft_filter_fff.h
index 309a55135..8eb0a1c83 100644
--- a/gr-filter/include/filter/fft_filter_fff.h
+++ b/gr-filter/include/filter/fft_filter_fff.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -19,70 +19,49 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_GR_FFT_FILTER_FFF_H
-#define INCLUDED_GR_FFT_FILTER_FFF_H
-#include
-#include
-
-class gr_fft_filter_fff;
-typedef boost::shared_ptr gr_fft_filter_fff_sptr;
-GR_CORE_API gr_fft_filter_fff_sptr
-gr_make_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads=1);
-
-class gri_fft_filter_fff_generic;
-//class gri_fft_filter_fff_sse;
+#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_H
+#define INCLUDED_FILTER_FFT_FILTER_FFF_H
-/*!
- * \brief Fast FFT filter with float input, float output and float taps
- * \ingroup filter_blk
- */
-class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator
-{
- private:
- friend GR_CORE_API gr_fft_filter_fff_sptr
- gr_make_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads);
+#include
+#include
- int d_nsamples;
- bool d_updated;
-#if 1 // don't enable the sse version until handling it is worked out
- gri_fft_filter_fff_generic *d_filter;
-#else
- gri_fft_filter_fff_sse *d_filter;
-#endif
- std::vector d_new_taps;
+namespace gr {
+ namespace filter {
- /*!
- * Construct a FFT filter with the given taps
- *
- * \param decimation >= 1
- * \param taps float filter taps
- * \param nthreads number of threads for the FFT to use
- */
- gr_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads=1);
+ class FILTER_API fft_filter_fff : virtual public gr_sync_decimator
+ {
+ public:
+ // gr::filter::fft_filter_fff::sptr
+ typedef boost::shared_ptr sptr;
- public:
- ~gr_fft_filter_fff ();
+ /*!
+ * \brief Fast FFT filter with float input, float output and float taps
+ * \ingroup filter_blk
+ *
+ * \param decimation >= 1
+ * \param taps float filter taps
+ * \param nthreads number of threads for the FFT to use
+ */
+ static FILTER_API sptr make(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
- void set_taps (const std::vector &taps);
- std::vector taps () const;
+ virtual void set_taps(const std::vector &taps) = 0;
+ virtual std::vector taps() const = 0;
- /*!
- * \brief Set number of threads to use.
- */
- void set_nthreads(int n);
+ /*!
+ * \brief Set number of threads to use.
+ */
+ virtual void set_nthreads(int n) = 0;
- /*!
- * \brief Get number of threads being used.
- */
- int nthreads() const;
+ /*!
+ * \brief Get number of threads being used.
+ */
+ virtual int nthreads() const = 0;
+ };
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
+ } /* namespace filter */
+} /* namespace gr */
-#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */
+#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_H */
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
index 525532fe6..76b00cae9 100644
--- a/gr-filter/include/filter/fir_filter.h
+++ b/gr-filter/include/filter/fir_filter.h
@@ -110,7 +110,7 @@ namespace gr {
gr_complex *d_taps;
};
- } /* namespace impl */
+ } /* namespace kernel */
} /* namespace filter */
} /* namespace gr */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index aa03c4615..e0af76700 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -109,6 +109,7 @@ list(APPEND filter_sources
fft_filter.cc
${generated_sources}
fft_filter_ccc_impl.cc
+ fft_filter_fff_impl.cc
)
list(APPEND filter_libs
diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc
index 86b2a2fdb..130886d7f 100644
--- a/gr-filter/lib/fft_filter.cc
+++ b/gr-filter/lib/fft_filter.cc
@@ -33,6 +33,146 @@ namespace gr {
namespace kernel {
#define VERBOSE 0
+
+ fft_filter_fff::fft_filter_fff(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0),
+ d_invfft(0), d_nthreads(nthreads)
+ {
+ set_taps(taps);
+ }
+
+ fft_filter_fff::~fft_filter_fff()
+ {
+ delete d_fwdfft;
+ delete d_invfft;
+ fft::free(d_xformed_taps);
+ }
+
+ /*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+ int
+ fft_filter_fff::set_taps(const std::vector &taps)
+ {
+ int i = 0;
+ compute_sizes(taps.size());
+
+ d_tail.resize(tailsize());
+ for(i = 0; i < tailsize(); i++)
+ d_tail[i] = 0;
+
+ float *in = d_fwdfft->get_inbuf();
+ gr_complex *out = d_fwdfft->get_outbuf();
+
+ float scale = 1.0 / d_fftsize;
+
+ // Compute forward xform of taps.
+ // Copy taps into first ntaps slots, then pad with zeros
+ for (i = 0; i < d_ntaps; i++)
+ in[i] = taps[i] * scale;
+
+ for (; i < d_fftsize; i++)
+ in[i] = 0;
+
+ d_fwdfft->execute(); // do the xform
+
+ // now copy output to d_xformed_taps
+ for (i = 0; i < d_fftsize/2+1; i++)
+ d_xformed_taps[i] = out[i];
+
+ return d_nsamples;
+ }
+
+ // determine and set d_ntaps, d_nsamples, d_fftsize
+ void
+ fft_filter_fff::compute_sizes(int ntaps)
+ {
+ int old_fftsize = d_fftsize;
+ d_ntaps = ntaps;
+ d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0))));
+ d_nsamples = d_fftsize - d_ntaps + 1;
+
+ if(VERBOSE) {
+ std::cerr << "fft_filter_fff: ntaps = " << d_ntaps
+ << " fftsize = " << d_fftsize
+ << " nsamples = " << d_nsamples << std::endl;
+ }
+
+ // compute new plans
+ if(d_fftsize != old_fftsize) {
+ delete d_fwdfft;
+ delete d_invfft;
+ d_fwdfft = new fft::fft_real_fwd(d_fftsize);
+ d_invfft = new fft::fft_real_rev(d_fftsize);
+ d_xformed_taps = fft::malloc_complex(d_fftsize/2+1);
+ }
+ }
+
+ void
+ fft_filter_fff::set_nthreads(int n)
+ {
+ d_nthreads = n;
+ if(d_fwdfft)
+ d_fwdfft->set_nthreads(n);
+ if(d_invfft)
+ d_invfft->set_nthreads(n);
+ }
+
+ int
+ fft_filter_fff::nthreads() const
+ {
+ return d_nthreads;
+ }
+
+ int
+ fft_filter_fff::filter(int nitems, const float *input, float *output)
+ {
+ int dec_ctr = 0;
+ int j = 0;
+ int ninput_items = nitems * d_decimation;
+
+ for (int i = 0; i < ninput_items; i += d_nsamples){
+
+ memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float));
+
+ for (j = d_nsamples; j < d_fftsize; j++)
+ d_fwdfft->get_inbuf()[j] = 0;
+
+ d_fwdfft->execute(); // compute fwd xform
+
+ gr_complex *a = d_fwdfft->get_outbuf();
+ gr_complex *b = d_xformed_taps;
+ gr_complex *c = d_invfft->get_inbuf();
+
+ volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize/2+1);
+
+ d_invfft->execute(); // compute inv xform
+
+ // add in the overlapping tail
+ for (j = 0; j < tailsize(); j++)
+ d_invfft->get_outbuf()[j] += d_tail[j];
+
+ // copy nsamples to output
+ j = dec_ctr;
+ while (j < d_nsamples) {
+ *output++ = d_invfft->get_outbuf()[j];
+ j += d_decimation;
+ }
+ dec_ctr = (j - d_nsamples);
+
+ // stash the tail
+ memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+ tailsize() * sizeof(float));
+ }
+
+ return nitems;
+ }
+
+
+ /**************************************************************/
+
fft_filter_ccc::fft_filter_ccc(int decimation,
const std::vector &taps,
@@ -127,7 +267,7 @@ namespace gr {
}
int
- fft_filter_ccc::filter (int nitems, const gr_complex *input, gr_complex *output)
+ fft_filter_ccc::filter(int nitems, const gr_complex *input, gr_complex *output)
{
int dec_ctr = 0;
int j = 0;
@@ -169,6 +309,7 @@ namespace gr {
return nitems;
}
- } /* namespace impl */
+
+ } /* namespace kernel */
} /* namespace filter */
} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_ccc_impl.h b/gr-filter/lib/fft_filter_ccc_impl.h
index 2d8d61c5e..82be00915 100644
--- a/gr-filter/lib/fft_filter_ccc_impl.h
+++ b/gr-filter/lib/fft_filter_ccc_impl.h
@@ -39,8 +39,8 @@ namespace gr {
public:
fft_filter_ccc_impl(int decimation,
- const std::vector &taps,
- int nthreads=1);
+ const std::vector &taps,
+ int nthreads=1);
~fft_filter_ccc_impl();
@@ -50,9 +50,9 @@ namespace gr {
void set_nthreads(int n);
int nthreads() 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 filter */
diff --git a/gr-filter/lib/fft_filter_fff_impl.cc b/gr-filter/lib/fft_filter_fff_impl.cc
index a09feb7f1..95b82aae5 100644
--- a/gr-filter/lib/fft_filter_fff_impl.cc
+++ b/gr-filter/lib/fft_filter_fff_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2010 Free Software Foundation, Inc.
+ * Copyright 2005,2010,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -24,100 +24,97 @@
#include "config.h"
#endif
-#include
-#include
+#include "fft_filter_fff_impl.h"
#include
+
+#include
#include
#include
-
-#include
-#include
-#include
-
-gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation,
- const std::vector &taps,
- int nthreads)
-{
- return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps, nthreads));
-}
-
-
-gr_fft_filter_fff::gr_fft_filter_fff (int decimation,
- const std::vector &taps,
- int nthreads)
- : gr_sync_decimator ("fft_filter_fff",
- gr_make_io_signature (1, 1, sizeof (float)),
- gr_make_io_signature (1, 1, sizeof (float)),
- decimation),
- d_updated(false)
-{
- set_history(1);
-
-#if 1 // don't enable the sse version until handling it is worked out
- d_filter = new gri_fft_filter_fff_generic(decimation, taps, nthreads);
-#else
- d_filter = new gri_fft_filter_fff_sse(decimation, taps);
-#endif
-
- d_new_taps = taps;
- d_nsamples = d_filter->set_taps(taps);
- set_output_multiple(d_nsamples);
-}
-
-gr_fft_filter_fff::~gr_fft_filter_fff ()
-{
- delete d_filter;
-}
-
-void
-gr_fft_filter_fff::set_taps (const std::vector &taps)
-{
- d_new_taps = taps;
- d_updated = true;
-}
-
-std::vector
-gr_fft_filter_fff::taps () const
-{
- return d_new_taps;
-}
-
-void
-gr_fft_filter_fff::set_nthreads(int n)
-{
- if(d_filter)
- d_filter->set_nthreads(n);
-}
-
-int
-gr_fft_filter_fff::nthreads() const
-{
- if(d_filter)
- return d_filter->nthreads();
- else
- return 0;
-}
-
-int
-gr_fft_filter_fff::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];
- float *out = (float *) output_items[0];
-
- if (d_updated){
- d_nsamples = d_filter->set_taps(d_new_taps);
- d_updated = false;
- set_output_multiple(d_nsamples);
- return 0; // output multiple may have changed
- }
-
- assert(noutput_items % d_nsamples == 0);
-
- d_filter->filter(noutput_items, in, out);
-
- //assert((out - (float *) output_items[0]) == noutput_items);
-
- return noutput_items;
-}
+#include
+
+namespace gr {
+ namespace filter {
+
+ fft_filter_fff::sptr fft_filter_fff::make(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ {
+ return gnuradio::get_initial_sptr(new fft_filter_fff_impl
+ (decimation, taps, nthreads));
+ }
+
+
+ fft_filter_fff_impl::fft_filter_fff_impl(int decimation,
+ const std::vector &taps,
+ int nthreads)
+ : gr_sync_decimator("fft_filter_fff",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature (1, 1, sizeof(float)),
+ decimation),
+ d_updated(false)
+ {
+ set_history(1);
+
+ d_filter = new kernel::fft_filter_fff(decimation, taps, nthreads);
+
+ d_new_taps = taps;
+ d_nsamples = d_filter->set_taps(taps);
+ set_output_multiple(d_nsamples);
+ }
+
+ fft_filter_fff_impl::~fft_filter_fff_impl()
+ {
+ delete d_filter;
+ }
+
+ void
+ fft_filter_fff_impl::set_taps(const std::vector &taps)
+ {
+ d_new_taps = taps;
+ d_updated = true;
+ }
+
+ std::vector
+ fft_filter_fff_impl::taps() const
+ {
+ return d_new_taps;
+ }
+
+ void
+ fft_filter_fff_impl::set_nthreads(int n)
+ {
+ if(d_filter)
+ d_filter->set_nthreads(n);
+ }
+
+ int
+ fft_filter_fff_impl::nthreads() const
+ {
+ if(d_filter)
+ return d_filter->nthreads();
+ else
+ return 0;
+ }
+
+ int
+ fft_filter_fff_impl::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];
+ float *out = (float *)output_items[0];
+
+ if (d_updated){
+ d_nsamples = d_filter->set_taps(d_new_taps);
+ d_updated = false;
+ set_output_multiple(d_nsamples);
+ return 0; // output multiple may have changed
+ }
+
+ d_filter->filter(noutput_items, in, out);
+
+ return noutput_items;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/fft_filter_fff_impl.h b/gr-filter/lib/fft_filter_fff_impl.h
index 309a55135..df35d3df7 100644
--- a/gr-filter/lib/fft_filter_fff_impl.h
+++ b/gr-filter/lib/fft_filter_fff_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -19,70 +19,43 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_GR_FFT_FILTER_FFF_H
-#define INCLUDED_GR_FFT_FILTER_FFF_H
-
-#include
-#include
-
-class gr_fft_filter_fff;
-typedef boost::shared_ptr gr_fft_filter_fff_sptr;
-GR_CORE_API gr_fft_filter_fff_sptr
-gr_make_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads=1);
-
-class gri_fft_filter_fff_generic;
-//class gri_fft_filter_fff_sse;
-
-/*!
- * \brief Fast FFT filter with float input, float output and float taps
- * \ingroup filter_blk
- */
-class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator
-{
- private:
- friend GR_CORE_API gr_fft_filter_fff_sptr
- gr_make_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads);
-
- int d_nsamples;
- bool d_updated;
-#if 1 // don't enable the sse version until handling it is worked out
- gri_fft_filter_fff_generic *d_filter;
-#else
- gri_fft_filter_fff_sse *d_filter;
-#endif
- std::vector d_new_taps;
-
- /*!
- * Construct a FFT filter with the given taps
- *
- * \param decimation >= 1
- * \param taps float filter taps
- * \param nthreads number of threads for the FFT to use
- */
- gr_fft_filter_fff (int decimation, const std::vector &taps,
- int nthreads=1);
-
- public:
- ~gr_fft_filter_fff ();
-
- void set_taps (const std::vector &taps);
- std::vector taps () const;
-
- /*!
- * \brief Set number of threads to use.
- */
- void set_nthreads(int n);
-
- /*!
- * \brief Get number of threads being used.
- */
- int nthreads() const;
-
- int work (int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */
+#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H
+#define INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H
+
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API fft_filter_fff_impl : public fft_filter_fff
+ {
+ private:
+ int d_nsamples;
+ bool d_updated;
+ kernel::fft_filter_fff *d_filter;
+ std::vector d_new_taps;
+
+ public:
+ fft_filter_fff_impl(int decimation,
+ const std::vector &taps,
+ int nthreads=1);
+
+ ~fft_filter_fff_impl();
+
+ void set_taps(const std::vector &taps);
+ std::vector taps() const;
+
+ void set_nthreads(int n);
+ int nthreads() const;
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H */
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
index 321f6981e..b45209aa7 100644
--- a/gr-filter/lib/fir_filter.cc
+++ b/gr-filter/lib/fir_filter.cc
@@ -263,6 +263,6 @@ namespace gr {
}
}
- } /* namespace impl */
+ } /* namespace kernel */
} /* namespace filter */
} /* namespace gr */
diff --git a/gr-filter/python/qa_fft_filter.py b/gr-filter/python/qa_fft_filter.py
index 33d3d870b..87d64df36 100755
--- a/gr-filter/python/qa_fft_filter.py
+++ b/gr-filter/python/qa_fft_filter.py
@@ -216,7 +216,7 @@ class test_fft_filter(gr_unittest.TestCase):
taps = (1,)
expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(1, taps)
+ op = filter.fft_filter_fff(1, taps)
dst = gr.vector_sink_f()
tb.connect(src, op, dst)
tb.run()
@@ -232,7 +232,7 @@ class test_fft_filter(gr_unittest.TestCase):
taps = (2,)
expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(1, taps)
+ op = filter.fft_filter_fff(1, taps)
dst = gr.vector_sink_f()
tb.connect(src, op, dst)
tb.run()
@@ -249,7 +249,7 @@ class test_fft_filter(gr_unittest.TestCase):
nthreads = 2
expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(1, taps, nthreads)
+ op = filter.fft_filter_fff(1, taps, nthreads)
dst = gr.vector_sink_f()
tb.connect(src, op, dst)
tb.run()
@@ -267,7 +267,7 @@ class test_fft_filter(gr_unittest.TestCase):
expected_result = reference_filter_fff(1, taps, src_data)
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(1, taps)
+ op = filter.fft_filter_fff(1, taps)
dst = gr.vector_sink_f()
tb = gr.top_block()
tb.connect(src, op, dst)
@@ -297,7 +297,7 @@ class test_fft_filter(gr_unittest.TestCase):
expected_result = reference_filter_fff(1, taps, src_data)
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(1, taps)
+ op = filter.fft_filter_fff(1, taps)
dst = gr.vector_sink_f()
tb = gr.top_block()
tb.connect(src, op, dst)
@@ -318,7 +318,7 @@ class test_fft_filter(gr_unittest.TestCase):
expected_result = reference_filter_fff(dec, taps, src_data)
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(dec, taps)
+ op = filter.fft_filter_fff(dec, taps)
dst = gr.vector_sink_f()
tb = gr.top_block()
tb.connect(src, op, dst)
@@ -341,7 +341,7 @@ class test_fft_filter(gr_unittest.TestCase):
expected_result = reference_filter_fff(dec, taps, src_data)
src = gr.vector_source_f(src_data)
- op = gr.fft_filter_fff(dec, taps, nthreads)
+ op = filter.fft_filter_fff(dec, taps, nthreads)
dst = gr.vector_sink_f()
tb = gr.top_block()
tb.connect(src, op, dst)
@@ -356,7 +356,7 @@ class test_fft_filter(gr_unittest.TestCase):
ntaps = int(random.uniform(2, 100))
taps = make_random_float_tuple(ntaps)
- op = gr.fft_filter_fff(1, taps)
+ op = filter.fft_filter_fff(1, taps)
result_data = op.taps()
#print result_data
@@ -368,7 +368,7 @@ class test_fft_filter(gr_unittest.TestCase):
ntaps = int(random.uniform(2, 100))
taps = make_random_complex_tuple(ntaps)
- op = gr.fft_filter_ccc(1, taps)
+ op = filter.fft_filter_ccc(1, taps)
result_data = op.taps()
#print result_data
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index 94ad9cd64..6010455b7 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -32,14 +32,17 @@
#include "filter/fir_filter_ccf.h"
#include "filter/fir_filter_ccc.h"
#include "filter/fft_filter_ccc.h"
+#include "filter/fft_filter_fff.h"
%}
%include "filter/fir_filter_fff.h"
%include "filter/fir_filter_ccf.h"
%include "filter/fir_filter_ccc.h"
%include "filter/fft_filter_ccc.h"
+%include "filter/fft_filter_fff.h"
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff);
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc);
GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc);
+GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff);
--
cgit
From 42eeb8736a50f13a36cc5b40e9465af03b64b2af Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Wed, 2 May 2012 20:03:41 -0400
Subject: filter: fixed fft_filter tests.
---
gr-filter/python/qa_fft_filter.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/gr-filter/python/qa_fft_filter.py b/gr-filter/python/qa_fft_filter.py
index 87d64df36..eaef3156d 100755
--- a/gr-filter/python/qa_fft_filter.py
+++ b/gr-filter/python/qa_fft_filter.py
@@ -97,7 +97,7 @@ class test_fft_filter(gr_unittest.TestCase):
taps = (1,)
expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_c(src_data)
- op = gr.fft_filter_ccc(1, taps)
+ op = filter.fft_filter_ccc(1, taps)
dst = gr.vector_sink_c()
tb.connect(src, op, dst)
tb.run()
@@ -115,7 +115,7 @@ class test_fft_filter(gr_unittest.TestCase):
nthreads = 2
expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_c(src_data)
- op = gr.fft_filter_ccc(1, taps, nthreads)
+ op = filter.fft_filter_ccc(1, taps, nthreads)
dst = gr.vector_sink_c()
tb.connect(src, op, dst)
tb.run()
@@ -130,7 +130,7 @@ class test_fft_filter(gr_unittest.TestCase):
taps = (2,)
expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)])
src = gr.vector_source_c(src_data)
- op = gr.fft_filter_ccc(1, taps)
+ op = filter.fft_filter_ccc(1, taps)
dst = gr.vector_sink_c()
tb.connect(src, op, dst)
tb.run()
@@ -172,7 +172,7 @@ class test_fft_filter(gr_unittest.TestCase):
expected_result = reference_filter_ccc(dec, taps, src_data)
src = gr.vector_source_c(src_data)
- op = gr.fft_filter_ccc(dec, taps)
+ op = filter.fft_filter_ccc(dec, taps)
dst = gr.vector_sink_c()
tb = gr.top_block()
tb.connect(src, op, dst)
--
cgit
From 9968eb116b89f2a38602d590207fbe0ea514c018 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Thu, 3 May 2012 12:17:35 -0400
Subject: filter: preparing to handle alignment better in FIR filters.
---
gr-filter/include/filter/fir_filter.h | 1 +
gr-filter/lib/fir_filter.cc | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h
index 76b00cae9..fba4641bf 100644
--- a/gr-filter/include/filter/fir_filter.h
+++ b/gr-filter/include/filter/fir_filter.h
@@ -54,6 +54,7 @@ namespace gr {
private:
unsigned int d_ntaps;
float *d_taps;
+ float *d_aligned_taps[4];
};
/**************************************************************/
diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc
index b45209aa7..3abcda53e 100644
--- a/gr-filter/lib/fir_filter.cc
+++ b/gr-filter/lib/fir_filter.cc
@@ -57,6 +57,12 @@ namespace gr {
for(unsigned int i = 0; i < d_ntaps; i++) {
d_taps[d_ntaps-i-1] = taps[i];
}
+
+ for(int i = 0; i < 4; i++) {
+ d_aligned_taps[i] = fft::malloc_float(d_ntaps+3);
+ memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+3));
+ memcpy(&d_aligned_taps[i][i], d_taps, sizeof(float)*(d_ntaps));
+ }
}
std::vector
@@ -78,6 +84,9 @@ namespace gr {
fir_filter_fff::filter(const float input[])
{
float output;
+
+ //const float *ar = (float*)((unsigned long)input & ~15);
+
volk_32f_x2_dot_prod_32f_u(&output, input, d_taps, d_ntaps);
return output;
}
--
cgit
From 2c80be2c6e3aadcc96046c2e99891c54f61b027c Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Thu, 3 May 2012 13:33:54 -0400
Subject: filter: improved documentation for fft_filters.
---
gr-filter/include/filter/fft_filter_ccc.h | 19 +++++++++++++++++++
gr-filter/include/filter/fft_filter_fff.h | 19 +++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/gr-filter/include/filter/fft_filter_ccc.h b/gr-filter/include/filter/fft_filter_ccc.h
index 29fd54713..c018629a9 100644
--- a/gr-filter/include/filter/fft_filter_ccc.h
+++ b/gr-filter/include/filter/fft_filter_ccc.h
@@ -39,6 +39,25 @@ namespace gr {
* \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
* \ingroup filter_blk
*
+ * This block implements a complex decimating filter using the
+ * fast convolution method via an FFT. The decimation factor is
+ * an interger that is greater than or equal to 1.
+ *
+ * The filter takes a set of complex (or real) taps to use in
+ * the filtering operation. These taps can be defined as
+ * anything that satisfies the user's filtering needs. For
+ * standard filters such as lowpass, highpass, bandpass, etc.,
+ * the filter.firdes and filter.optfir classes provide
+ * convenient generating methods.
+ *
+ * This filter is implemented by using the FFTW package to
+ * perform the required FFTs. An optional argument, nthreads,
+ * may be passed to the constructor (or set using the
+ * set_nthreads member function) to split the FFT among N number
+ * of threads. This can improve performance on very large FFTs
+ * (that is, if the number of taps used is very large) if you
+ * have enough threads/cores to support it.
+ *
* \param decimation >= 1
* \param taps complex filter taps
* \param nthreads number of threads for the FFT to use
diff --git a/gr-filter/include/filter/fft_filter_fff.h b/gr-filter/include/filter/fft_filter_fff.h
index 8eb0a1c83..78540666c 100644
--- a/gr-filter/include/filter/fft_filter_fff.h
+++ b/gr-filter/include/filter/fft_filter_fff.h
@@ -39,6 +39,25 @@ namespace gr {
* \brief Fast FFT filter with float input, float output and float taps
* \ingroup filter_blk
*
+ * This block implements a real-value decimating filter using
+ * the fast convolution method via an FFT. The decimation factor
+ * is an interger that is greater than or equal to 1.
+ *
+ * The filter takes a set of real-valued taps to use in
+ * the filtering operation. These taps can be defined as
+ * anything that satisfies the user's filtering needs. For
+ * standard filters such as lowpass, highpass, bandpass, etc.,
+ * the filter.firdes and filter.optfir classes provide
+ * convenient generating methods.
+ *
+ * This filter is implemented by using the FFTW package to
+ * perform the required FFTs. An optional argument, nthreads,
+ * may be passed to the constructor (or set using the
+ * set_nthreads member function) to split the FFT among N number
+ * of threads. This can improve performance on very large FFTs
+ * (that is, if the number of taps used is very large) if you
+ * have enough threads/cores to support it.
+ *
* \param decimation >= 1
* \param taps float filter taps
* \param nthreads number of threads for the FFT to use
--
cgit
From 1e18d093dad92f798796f75136943adf088cfe60 Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Thu, 3 May 2012 14:05:21 -0400
Subject: filter: added GRC block for FFT filters. Fixed example install.
---
gr-filter/CMakeLists.txt | 4 ++-
gr-filter/examples/CMakeLists.txt | 4 ++-
gr-filter/grc/CMakeLists.txt | 1 +
gr-filter/grc/fft_filter_xxx.xml | 59 +++++++++++++++++++++++++++++++++++++
gr-filter/grc/filter_block_tree.xml | 1 +
5 files changed, 67 insertions(+), 2 deletions(-)
create mode 100644 gr-filter/grc/fft_filter_xxx.xml
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
index 02b8f23fe..b77a3d9d4 100644
--- a/gr-filter/CMakeLists.txt
+++ b/gr-filter/CMakeLists.txt
@@ -42,6 +42,8 @@ GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}/include
)
+SET(GR_PKG_FILTER_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/filter)
+
########################################################################
# Begin conditional configuration
########################################################################
@@ -91,7 +93,7 @@ if(ENABLE_PYTHON)
add_subdirectory(python)
add_subdirectory(grc)
endif(ENABLE_PYTHON)
-#add_subdirectory(examples)
+add_subdirectory(examples)
add_subdirectory(doc)
########################################################################
diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt
index c798a8403..12a3c42e0 100644
--- a/gr-filter/examples/CMakeLists.txt
+++ b/gr-filter/examples/CMakeLists.txt
@@ -22,6 +22,8 @@ include(GrPython)
# Base stuff
GR_PYTHON_INSTALL(PROGRAMS
fir_filter_fff.py
- DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}
+ fir_filter_ccc.py
+ fft_filter_ccc.py
+ DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR}
COMPONENT "filter_python"
)
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 79496183f..9b40395b8 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -19,6 +19,7 @@
install(FILES
filter_block_tree.xml
+ fft_filter_xxx.xml
DESTINATION ${GRC_BLOCKS_DIR}
COMPONENT "filter_python"
)
diff --git a/gr-filter/grc/fft_filter_xxx.xml b/gr-filter/grc/fft_filter_xxx.xml
new file mode 100644
index 000000000..29612dffd
--- /dev/null
+++ b/gr-filter/grc/fft_filter_xxx.xml
@@ -0,0 +1,59 @@
+
+
+
+ FFT Filter
+ fft_filter_xxx
+ from gnuradio import filter
+ from gnuradio.gr import firdes
+ filter.fft_filter_$(type)($decim, $taps, $nthreads)
+ set_taps($taps)
+ set_nthreads($nthreads)
+
+ Type
+ type
+ enum
+
+
+
+
+ Decimation
+ decim
+ 1
+ int
+
+
+ Taps
+ taps
+ $type.taps
+
+
+ Num. Threads
+ nthreads
+ 1
+ int
+
+
+ in
+ $type.input
+
+
+ out
+ $type.output
+
+
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
index a97620db9..7d0559857 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -30,5 +30,6 @@
Filters
+ fft_filter_xxx
--
cgit
From 906fe742d1c6a6ca93b47261b0ee615d4779081b Mon Sep 17 00:00:00 2001
From: Tom Rondeau
Date: Sat, 5 May 2012 13:34:56 -0400
Subject: filter: added firdes for generating FIR filters to gr-filter.
Addes QA code in both Python and C++.
---
gr-filter/include/filter/CMakeLists.txt | 1 +
gr-filter/include/filter/firdes.h | 378 ++++++++++++++
gr-filter/lib/CMakeLists.txt | 22 +
gr-filter/lib/firdes.cc | 855 ++++++++++++++++++++++++++++++++
gr-filter/lib/qa_filter.cc | 39 ++
gr-filter/lib/qa_filter.h | 38 ++
gr-filter/lib/qa_firdes.cc | 621 +++++++++++++++++++++++
gr-filter/lib/qa_firdes.h | 56 +++
gr-filter/lib/test_gr_filter.cc | 42 ++
gr-filter/python/qa_fir_filter.py | 2 +-
gr-filter/python/qa_firdes.py | 202 ++++++++
gr-filter/swig/filter_swig.i | 2 +
12 files changed, 2257 insertions(+), 1 deletion(-)
create mode 100644 gr-filter/include/filter/firdes.h
create mode 100644 gr-filter/lib/firdes.cc
create mode 100644 gr-filter/lib/qa_filter.cc
create mode 100644 gr-filter/lib/qa_filter.h
create mode 100644 gr-filter/lib/qa_firdes.cc
create mode 100644 gr-filter/lib/qa_firdes.h
create mode 100644 gr-filter/lib/test_gr_filter.cc
create mode 100755 gr-filter/python/qa_firdes.py
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index f96128805..108509e9a 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -75,6 +75,7 @@ add_custom_target(filter_generated_includes DEPENDS
########################################################################
install(FILES
api.h
+ firdes.h
fir_filter.h
fft_filter.h
${generated_includes}
diff --git a/gr-filter/include/filter/firdes.h b/gr-filter/include/filter/firdes.h
new file mode 100644
index 000000000..172563ea0
--- /dev/null
+++ b/gr-filter/include/filter/firdes.h
@@ -0,0 +1,378 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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 _FILTER_FIRDES_H_
+#define _FILTER_FIRDES_H_
+
+#include
+#include
+#include
+#include
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \brief Finite Impulse Response (FIR) filter design functions.
+ * \ingroup filter_design
+ */
+
+ class FILTER_API firdes {
+ public:
+
+ enum win_type {
+ WIN_HAMMING = 0, // max attenuation 53 dB
+ WIN_HANN = 1, // max attenuation 44 dB
+ WIN_BLACKMAN = 2, // max attenuation 74 dB
+ WIN_RECTANGULAR = 3,
+ WIN_KAISER = 4, // max attenuation a function of beta, google it
+ WIN_BLACKMAN_hARRIS = 5,
+ WIN_BLACKMAN_HARRIS = 5, // alias for capitalization consistency
+ };
+
+
+ // ... class methods ...
+
+ /*!
+ * \brief use "window method" to design a low-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector
+ low_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a low-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB required stopband attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuatin --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ low_pass_2(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a high-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ high_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a high-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ high_pass_2(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector
+ band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a complex band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+ static std::vector
+ complex_band_pass(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a complex band-pass FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ complex_band_pass_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-reject FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * The normalized width of the transition
+ * band is what sets the number of taps
+ * required. Narrow --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ band_reject(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz center of transition band
+ double high_cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!
+ * \brief use "window method" to design a band-reject FIR filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p low_cutoff_freq: center of transition band (Hz)
+ * \p high_cutoff_freq: center of transition band (Hz)
+ * \p transition_width: width of transition band (Hz).
+ * \p attenuation_dB out of band attenuation
+ * The normalized width of the transition
+ * band and the required stop band
+ * attenuation is what sets the number of taps
+ * required. Narrow --> more taps
+ * More attenuation --> more taps
+ * \p window_type: What kind of window to use. Determines
+ * maximum attenuation and passband ripple.
+ * \p beta: parameter for Kaiser window
+ */
+
+ static std::vector
+ band_reject_2(double gain,
+ double sampling_freq,
+ double low_cutoff_freq, // Hz beginning transition band
+ double high_cutoff_freq, // Hz beginning transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // out of band attenuation dB
+ win_type window = WIN_HAMMING,
+ double beta = 6.76); // used only with Kaiser
+
+ /*!\brief design a Hilbert Transform Filter
+ *
+ * \p ntaps: Number of taps, must be odd
+ * \p window_type: What kind of window to use
+ * \p beta: Only used for Kaiser
+ */
+ static std::vector
+ hilbert(unsigned int ntaps = 19,
+ win_type windowtype = WIN_RECTANGULAR,
+ double beta = 6.76);
+
+ /*!
+ * \brief design a Root Cosine FIR Filter (do we need a window?)
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p sampling_freq: sampling freq (Hz)
+ * \p symbol rate: symbol rate, must be a factor of sample rate
+ * \p alpha: excess bandwidth factor
+ * \p ntaps: number of taps
+ */
+ static std::vector
+ root_raised_cosine(double gain,
+ double sampling_freq,
+ double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK)
+ double alpha, // Excess Bandwidth Factor
+ int ntaps);
+
+ /*!
+ * \brief design a Gaussian filter
+ *
+ * \p gain: overall gain of filter (typically 1.0)
+ * \p symbols per bit: symbol rate, must be a factor of sample rate
+ * \p ntaps: number of taps
+ */
+ static std::vector
+ gaussian(double gain,
+ double spb,
+ double bt, // Bandwidth to bitrate ratio
+ int ntaps);
+
+ // window functions ...
+ static std::vector window (win_type type, int ntaps, double beta);
+
+ private:
+ static double bessi0(double x);
+ static void sanity_check_1f(double sampling_freq, double f1,
+ double transition_width);
+ static void sanity_check_2f(double sampling_freq, double f1, double f2,
+ double transition_width);
+ static void sanity_check_2f_c(double sampling_freq, double f1, double f2,
+ double transition_width);
+
+ static int compute_ntaps(double sampling_freq,
+ double transition_width,
+ win_type window_type, double beta);
+
+ static int compute_ntaps_windes(double sampling_freq,
+ double transition_width,
+ double attenuation_dB);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* _FILTER_FIRDES_H_ */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index e0af76700..f085987de 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -107,6 +107,7 @@ link_directories(${FFTW3F_LIBRARY_DIRS})
list(APPEND filter_sources
fir_filter.cc
fft_filter.cc
+ firdes_impl.cc
${generated_sources}
fft_filter_ccc_impl.cc
fft_filter_fff_impl.cc
@@ -124,3 +125,24 @@ add_library(gnuradio-filter SHARED ${filter_sources})
target_link_libraries(gnuradio-filter ${filter_libs})
GR_LIBRARY_FOO(gnuradio-filter RUNTIME_COMPONENT "filter_runtime" DEVEL_COMPONENT "filter_devel")
add_dependencies(gnuradio-filter gnuradio-fft filter_generated_includes filter_generated_swigs)
+
+
+########################################################################
+# QA C++ Code for gr-filter
+########################################################################
+list(APPEND test_gr_filter_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_filter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_filter.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_firdes.cc
+)
+
+add_executable(test-gr-filter ${test_gr_filter_sources})
+target_link_libraries(
+ test-gr-filter
+ gnuradio-core
+ gnuradio-filter
+ ${CPPUNIT_LIBRARIES}
+ ${Boost_LIBRARIES}
+)
+
+GR_ADD_TEST(test_gr_filter)
diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc
new file mode 100644
index 000000000..5c3320d71
--- /dev/null
+++ b/gr-filter/lib/firdes.cc
@@ -0,0 +1,855 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+
+using std::vector;
+
+namespace gr {
+ namespace filter {
+
+#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
+
+ 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;
+ n += 1;
+ temp *= temp;
+ u *= temp;
+ sum += u;
+ } while (u >= IzeroEPSILON*sum);
+ return(sum);
+ }
+
+
+ //
+ // === Low Pass ===
+ //
+
+ vector
+ firdes::low_pass_2(double gain,
+ double sampling_freq, // Hz
+ double cutoff_freq, // Hz BEGINNING of transition band
+ double transition_width, // Hz width of transition band
+ double attenuation_dB, // attenuation dB
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps_windes(sampling_freq,
+ transition_width,
+ attenuation_dB);
+
+ // construct the truncated ideal impulse response
+ // [sin(x)/x for the low pass case]
+
+ vector taps(ntaps);
+ vector w = window(window_type, ntaps, beta);
+
+ int M = (ntaps - 1) / 2;
+ double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
+ for(int n = -M; n <= M; n++) {
+ if (n == 0)
+ taps[n + M] = fwT0 / M_PI * w[n + M];
+ else {
+ // a little algebra gets this into the more familiar sin(x)/x form
+ taps[n + M] = sin(n * fwT0) / (n * M_PI) * w[n + M];
+ }
+ }
+
+ // find the factor to normalize the gain, fmax.
+ // For low-pass, gain @ zero freq = 1.0
+
+ double fmax = taps[0 + M];
+ for(int n = 1; n <= M; n++)
+ fmax += 2 * taps[n + M];
+
+ gain /= fmax; // normalize
+
+ for(int i = 0; i < ntaps; i++)
+ taps[i] *= gain;
+
+ return taps;
+ }
+
+ vector
+ firdes::low_pass(double gain,
+ double sampling_freq,
+ double cutoff_freq, // Hz center of transition band
+ double transition_width, // Hz width of transition band
+ win_type window_type,
+ double beta) // used only with Kaiser
+ {
+ sanity_check_1f(sampling_freq, cutoff_freq, transition_width);
+
+ int ntaps = compute_ntaps(sampling_freq,
+ transition_width,
+ window_type, beta);
+
+ // construct the truncated ideal impulse response
+ // [sin(x)/x for the low pass case]
+
+ vector taps(ntaps);
+ vector