diff options
author | Tom Rondeau | 2012-05-02 18:59:23 -0400 |
---|---|---|
committer | Tom Rondeau | 2012-05-02 18:59:23 -0400 |
commit | 26531c2da601a1c21c50e3644350c604c27f8658 (patch) | |
tree | 1ddb4469afc96e508cc54b236c79657dd0c73363 /gr-filter/lib | |
parent | 32f807a8c8f1bcadfd8f8ad4c5a46c1b099f8c8f (diff) | |
download | gnuradio-26531c2da601a1c21c50e3644350c604c27f8658.tar.gz gnuradio-26531c2da601a1c21c50e3644350c604c27f8658.tar.bz2 gnuradio-26531c2da601a1c21c50e3644350c604c27f8658.zip |
filter: fixed FIR filter taps and added complex FFT filter.
Diffstat (limited to 'gr-filter/lib')
-rw-r--r-- | gr-filter/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gr-filter/lib/fft_filter.cc | 174 | ||||
-rw-r--r-- | gr-filter/lib/fft_filter_ccc_impl.cc | 119 | ||||
-rw-r--r-- | gr-filter/lib/fft_filter_ccc_impl.h | 61 | ||||
-rw-r--r-- | gr-filter/lib/fft_filter_fff_impl.cc | 123 | ||||
-rw-r--r-- | gr-filter/lib/fft_filter_fff_impl.h | 88 | ||||
-rw-r--r-- | gr-filter/lib/fir_filter.cc | 14 | ||||
-rw-r--r-- | gr-filter/lib/fir_filter_XXX_impl.cc.t | 8 | ||||
-rw-r--r-- | gr-filter/lib/fir_filter_XXX_impl.h.t | 2 |
9 files changed, 578 insertions, 13 deletions
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 <filter/fft_filter.h> +#include <volk/volk.h> +#include <iostream> + +namespace gr { + namespace filter { + namespace kernel { + + #define VERBOSE 0 + + fft_filter_ccc::fft_filter_ccc(int decimation, + const std::vector<gr_complex> &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<gr_complex> &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 <gr_io_signature.h> + +#include <math.h> +#include <assert.h> +#include <stdexcept> +#include <gr_firdes.h> + +namespace gr { + namespace filter { + + fft_filter_ccc::sptr fft_filter_ccc::make(int decimation, + const std::vector<gr_complex> &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<gr_complex> &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<gr_complex> &taps) + { + d_new_taps = taps; + d_updated = true; + } + + std::vector<gr_complex> + 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 <filter/api.h> +#include <filter/fft_filter.h> +#include <filter/fft_filter_ccc.h> + +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<gr_complex> d_new_taps; + + public: + fft_filter_ccc_impl(int decimation, + const std::vector<gr_complex> &taps, + int nthreads=1); + + ~fft_filter_ccc_impl(); + + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> 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 <gr_fft_filter_fff.h> +#include <gri_fft_filter_fff_generic.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> + +#include <cstdio> +#include <iostream> +#include <string.h> + +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, + const std::vector<float> &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<float> &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<float> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +std::vector<float> +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 <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_fft_filter_fff; +typedef boost::shared_ptr<gr_fft_filter_fff> gr_fft_filter_fff_sptr; +GR_CORE_API gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, const std::vector<float> &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<float> &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<float> 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<float> &taps, + int nthreads=1); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector<float> &taps); + std::vector<float> 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<float> &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<float> 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<float> 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<gr_complex> 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 <gr_io_signature.h> -#include <volk/volk.h> -#include <fft/fft.h> 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: |