From: Tom Rondeau Date: Wed, 28 Apr 2010 02:05:15 +0000 (-0400) Subject: Adding the synthesis filterbank (the opposite of the channelizer). It's ugly right... X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=06f92ca4200bbebd2ecb77f88b4524711f9292c4;p=debian%2Fgnuradio Adding the synthesis filterbank (the opposite of the channelizer). It's ugly right now and uses a lot of memory to handle the buffers for each filter/input stream. --- diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am index 23c1dadc..6a6532eb 100644 --- a/gnuradio-core/src/lib/filter/Makefile.am +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -205,6 +205,7 @@ libfilter_la_common_SOURCES = \ float_dotprod_generic.c \ short_dotprod_generic.c \ gr_pfb_channelizer_ccf.cc \ + gr_pfb_synthesis_filterbank_ccf.cc\ gr_pfb_decimator_ccf.cc \ gr_pfb_interpolator_ccf.cc \ gr_pfb_arb_resampler_ccf.cc \ @@ -288,6 +289,7 @@ grinclude_HEADERS = \ short_dotprod_x86.h \ sse_debug.h \ gr_pfb_channelizer_ccf.h \ + gr_pfb_synthesis_filterbank_ccf.h\ gr_pfb_decimator_ccf.h \ gr_pfb_interpolator_ccf.h \ gr_pfb_arb_resampler_ccf.h \ @@ -344,6 +346,7 @@ swiginclude_HEADERS = \ gr_single_pole_iir_filter_ff.i \ gr_single_pole_iir_filter_cc.i \ gr_pfb_channelizer_ccf.i \ + gr_pfb_synthesis_filterbank_ccf.i\ gr_pfb_decimator_ccf.i \ gr_pfb_interpolator_ccf.i \ gr_pfb_arb_resampler_ccf.i \ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i index bdfb8fa8..645607cb 100644 --- a/gnuradio-core/src/lib/filter/filter.i +++ b/gnuradio-core/src/lib/filter/filter.i @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ %include "gr_goertzel_fc.i" %include "gr_cma_equalizer_cc.i" %include "gr_pfb_channelizer_ccf.i" +%include "gr_pfb_synthesis_filterbank_ccf.i" %include "gr_pfb_decimator_ccf.i" %include "gr_pfb_interpolator_ccf.i" %include "gr_pfb_arb_resampler_ccf.i" diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc new file mode 100644 index 00000000..f8b0eae2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc @@ -0,0 +1,164 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 + +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps) +{ + return gr_pfb_synthesis_filterbank_ccf_sptr + (new gr_pfb_synthesis_filterbank_ccf (numchans, taps)); +} + + +gr_pfb_synthesis_filterbank_ccf::gr_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps) + : gr_sync_interpolator ("pfb_synthesis_filterbank_ccf", + gr_make_io_signature (numchans, numchans, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + numchans), + d_updated (false), d_numchans(numchans) +{ + d_filters = std::vector(d_numchans); + + d_buffer = new gr_complex*[d_numchans]; + + // Create an FIR filter for each channel and zero out the taps + std::vector vtaps(0, d_numchans); + for(unsigned int i = 0; i < d_numchans; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_buffer[i] = new gr_complex[65535]; + memset(d_buffer[i], 0, 65535*sizeof(gr_complex)); + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the IFFT to handle the input channel rotations + d_fft = new gri_fft_complex (d_numchans, true); +} + +gr_pfb_synthesis_filterbank_ccf::~gr_pfb_synthesis_filterbank_ccf () +{ + for(unsigned int i = 0; i < d_numchans; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_synthesis_filterbank_ccf::set_taps (const std::vector &taps) +{ + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter+1); + + d_updated = true; +} + +void +gr_pfb_synthesis_filterbank_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_numchans; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + + +int +gr_pfb_synthesis_filterbank_ccf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex*) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned int n, i; + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < d_numchans; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[i] = (in+i)[n]; + } + + // spin through IFFT + d_fft->execute(); + + for(i = 0; i < d_numchans; i++) { + d_buffer[i][n+d_taps_per_filter-1] = d_fft->get_outbuf()[i]; + out[i] = d_filters[i]->filter(&d_buffer[i][n]); + } + out += d_numchans; + } + + for(i = 0; i < d_numchans; i++) { + memcpy(d_buffer[i], &d_buffer[i][n], + (d_taps_per_filter)*sizeof(gr_complex)); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h new file mode 100644 index 00000000..4b6235a8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + + +#ifndef INCLUDED_GR_PFB_SYNTHESIS_FILTERBANK_CCF_H +#define INCLUDED_GR_PFB_SYNTHESIS_FILTERBANK_CCF_H + +#include + +class gr_pfb_synthesis_filterbank_ccf; +typedef boost::shared_ptr gr_pfb_synthesis_filterbank_ccf_sptr; +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + +class gr_fir_ccf; +class gri_fft_complex; + + +/*! + * \class gr_pfb_synthesis_filterbank_ccf + * + * \brief Polyphase synthesis filterbank with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + */ + +class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator +{ + private: + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of channels M + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + friend gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + + bool d_updated; + unsigned int d_numchans; + std::vector d_filters; + std::vector< std::vector > d_taps; + unsigned int d_taps_per_filter; + gri_fft_complex *d_fft; + gr_complex **d_buffer; + + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of channels M + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, + const std::vector &taps); + +public: + ~gr_pfb_synthesis_filterbank_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + void set_taps (const std::vector &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i new file mode 100644 index 00000000..02a9f025 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_synthesis_filterbank_ccf); + +gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf + (unsigned int numchans, const std::vector &taps); + +class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator +{ + private: + gr_pfb_synthesis_filterbank_ccf (unsigned int numchans, + const std::vector &taps); + + public: + ~gr_pfb_synthesis_filterbank_ccf (); + + void set_taps (const std::vector &taps); +};