summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-filter/grc/CMakeLists.txt1
-rw-r--r--gr-filter/grc/filter_block_tree.xml1
-rw-r--r--gr-filter/grc/pfb_arb_resampler.xml61
-rw-r--r--gr-filter/grc/pfb_decimator.xml2
-rw-r--r--gr-filter/include/filter/CMakeLists.txt2
-rw-r--r--gr-filter/include/filter/pfb_arb_resampler_ccf.h138
-rw-r--r--gr-filter/include/filter/pfb_arb_resampler_fff.h139
-rw-r--r--gr-filter/include/filter/pfb_decimator_ccf.h2
-rw-r--r--gr-filter/lib/CMakeLists.txt2
-rw-r--r--gr-filter/lib/pfb_arb_resampler_ccf_impl.cc235
-rw-r--r--gr-filter/lib/pfb_arb_resampler_ccf_impl.h86
-rw-r--r--gr-filter/lib/pfb_arb_resampler_fff_impl.cc237
-rw-r--r--gr-filter/lib/pfb_arb_resampler_fff_impl.h85
-rwxr-xr-xgr-filter/python/qa_pfb_arb_resampler.py95
-rw-r--r--gr-filter/swig/filter_swig.i6
15 files changed, 1090 insertions, 2 deletions
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 7fc129d8a..3110e0f1b 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -28,6 +28,7 @@ install(FILES
hilbert_fc.xml
iir_filter_ffd.xml
interp_fir_filter_xxx.xml
+ pfb_arb_resampler.xml
pfb_channelizer.xml
pfb_decimator.xml
pfb_interpolator.xml
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
index 0ec9e5dd0..ecc97dd23 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -39,6 +39,7 @@
<block>hilbert_fc</block>
<block>iir_filter_ffd</block>
<block>interp_fir_filter_xxx</block>
+ <block>pfb_arb_resampler_xxx</block>
<block>pfb_channelizer_ccf</block>
<block>pfb_decimator_ccf</block>
<block>pfb_interpolator_ccf</block>
diff --git a/gr-filter/grc/pfb_arb_resampler.xml b/gr-filter/grc/pfb_arb_resampler.xml
new file mode 100644
index 000000000..f3048000a
--- /dev/null
+++ b/gr-filter/grc/pfb_arb_resampler.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Polyphase Arbitrary Resampler
+###################################################
+ -->
+<block>
+ <name>Polyphase Arbitrary Resampler</name>
+ <key>pfb_arb_resampler_xxx</key>
+ <import>from gnuradio import filter</import>
+ <import>from gnuradio.filter import firdes</import>
+ <make>filter.pfb_arb_resampler_$(type)(
+ $rrate,
+ $taps,
+ $nfilts)
+ </make>
+ <callback>set_taps($taps)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex->Complex (Real Taps)</name>
+ <key>ccf</key>
+ <opt>input:complex</opt>
+ <opt>output:complex</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ <option>
+ <name>Float->Float (Real Taps)</name>
+ <key>fff</key>
+ <opt>input:float</opt>
+ <opt>output:float</opt>
+ <opt>taps:real_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Resampling Rate</name>
+ <key>rrate</key>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Taps</name>
+ <key>taps</key>
+ <type>$type.taps</type>
+ </param>
+ <param>
+ <name>Number of Filters</name>
+ <key>nfilts</key>
+ <value>32</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-filter/grc/pfb_decimator.xml b/gr-filter/grc/pfb_decimator.xml
index 329d59c3d..b0540d3e2 100644
--- a/gr-filter/grc/pfb_decimator.xml
+++ b/gr-filter/grc/pfb_decimator.xml
@@ -9,7 +9,7 @@
<key>pfb_decimator_ccf</key>
<import>from gnuradio import filter</import>
<import>from gnuradio.filter import firdes</import>
- <make>filter.pfb.decimator_ccf(
+ <make>filter.pfb_decimator_ccf(
$decim,
$taps,
$channel)
diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt
index 3d8e0c932..b0412aaba 100644
--- a/gr-filter/include/filter/CMakeLists.txt
+++ b/gr-filter/include/filter/CMakeLists.txt
@@ -100,6 +100,8 @@ install(FILES
fractional_interpolator_ff.h
hilbert_fc.h
iir_filter_ffd.h
+ pfb_arb_resampler_ccf.h
+ pfb_arb_resampler_fff.h
pfb_channelizer_ccf.h
pfb_decimator_ccf.h
pfb_interpolator_ccf.h
diff --git a/gr-filter/include/filter/pfb_arb_resampler_ccf.h b/gr-filter/include/filter/pfb_arb_resampler_ccf.h
new file mode 100644
index 000000000..1436674b2
--- /dev/null
+++ b/gr-filter/include/filter/pfb_arb_resampler_ccf.h
@@ -0,0 +1,138 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,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_PFB_ARB_RESAMPLER_CCF_H
+#define INCLUDED_PFB_ARB_RESAMPLER_CCF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_arb_resampler_ccf
+ *
+ * \brief Polyphase filterbank arbitrary resampler with
+ * gr_complex input, gr_complex output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs arbitrary
+ * resampling. The resampling rate can be any real number
+ * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
+ * filters where <EM>N</EM> is the interpolation rate. We then
+ * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
+ *
+ * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
+ * resampling where <EM>N/D</EM> is a rational number close to the
+ * input rate <EM>r</EM> where we have <EM>N</EM> filters and we
+ * cycle through them as a polyphase filterbank with a stride of
+ * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
+ *
+ * To get the arbitrary rate, we want to interpolate between two
+ * points. For each value out, we take an output from the current
+ * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
+ * linearly interpolate between the two based on the real
+ * resampling rate we want.
+ *
+ * The linear interpolation only provides us with an approximation
+ * to the real sampling rate specified. The error is a
+ * quantization error between the two filters we used as our
+ * interpolation points. To this end, the number of filters,
+ * <EM>N</EM>, used determines the quantization error; the larger
+ * <EM>N</EM>, the smaller the noise. You can design for a
+ * specified noise floor by setting the filter size (parameters
+ * <EM>filter_size</EM>). The size defaults to 32 filters, which
+ * is about as good as most implementations need.
+ *
+ * The trick with designing this filter is in how to specify the
+ * taps of the prototype filter. Like the PFB interpolator, the
+ * taps are specified using the interpolated filter rate. In this
+ * case, that rate is the input sample rate multiplied by the
+ * number of filters in the filterbank, which is also the
+ * interpolation rate. All other values should be relative to this
+ * rate.
+ *
+ * For example, for a 32-filter arbitrary resampler and using the
+ * GNU Radio's firdes utility to build the filter, we build a
+ * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
+ * bandwidth of <EM>BW</EM> and a transition bandwidth of
+ * <EM>TB</EM>. We can also specify the out-of-band attenuation to
+ * use, <EM>ATT</EM>, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the
+ * gain of the filter, which we specify here as the interpolation
+ * rate (<EM>32</EM>).
+ *
+ * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB,
+ * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 7.5 of
+ * the following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_arb_resampler_ccf : virtual public gr_block
+ {
+ public:
+ // gr::filter::pfb_arb_resampler_ccf::sptr
+ typedef boost::shared_ptr<pfb_arb_resampler_ccf> sptr;
+
+ /*!
+ * Build the polyphase filterbank arbitray resampler.
+ * \param rate (float) Specifies the resampling rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
+ * should be generated at the filter_size sampling rate.
+ * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
+ * related to quantization noise introduced during the resampling.
+ * Defaults to 32 filters.
+ */
+ static FILTER_API sptr make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size=32);
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ virtual void set_rate (float rate) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_H */
diff --git a/gr-filter/include/filter/pfb_arb_resampler_fff.h b/gr-filter/include/filter/pfb_arb_resampler_fff.h
new file mode 100644
index 000000000..7449ea0cb
--- /dev/null
+++ b/gr-filter/include/filter/pfb_arb_resampler_fff.h
@@ -0,0 +1,139 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-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_PFB_ARB_RESAMPLER_FFF_H
+#define INCLUDED_PFB_ARB_RESAMPLER_FFF_H
+
+#include <filter/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace filter {
+
+ /*!
+ * \class pfb_arb_resampler_fff
+ *
+ * \brief Polyphase filterbank arbitrary resampler with
+ * float input, float output and float taps
+ *
+ * \ingroup filter_blk
+ * \ingroup pfb_blk
+ *
+ * This block takes in a signal stream and performs arbitrary
+ * resampling. The resampling rate can be any real number
+ * <EM>r</EM>. The resampling is done by constructing <EM>N</EM>
+ * filters where <EM>N</EM> is the interpolation rate. We then
+ * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>.
+ *
+ * Using <EM>N</EM> and <EM>D</EM>, we can perform rational
+ * resampling where <EM>N/D</EM> is a rational number close to the
+ * input rate <EM>r</EM> where we have <EM>N</EM> filters and we
+ * cycle through them as a polyphase filterbank with a stride of
+ * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>.
+ *
+ * To get the arbitrary rate, we want to interpolate between two
+ * points. For each value out, we take an output from the current
+ * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then
+ * linearly interpolate between the two based on the real
+ * resampling rate we want.
+ *
+ * The linear interpolation only provides us with an approximation
+ * to the real sampling rate specified. The error is a
+ * quantization error between the two filters we used as our
+ * interpolation points. To this end, the number of filters,
+ * <EM>N</EM>, used determines the quantization error; the larger
+ * <EM>N</EM>, the smaller the noise. You can design for a
+ * specified noise floor by setting the filter size (parameters
+ * <EM>filter_size</EM>). The size defaults to 32 filters, which
+ * is about as good as most implementations need.
+ *
+ * The trick with designing this filter is in how to specify the
+ * taps of the prototype filter. Like the PFB interpolator, the
+ * taps are specified using the interpolated filter rate. In this
+ * case, that rate is the input sample rate multiplied by the
+ * number of filters in the filterbank, which is also the
+ * interpolation rate. All other values should be relative to this
+ * rate.
+ *
+ * For example, for a 32-filter arbitrary resampler and using the
+ * GNU Radio's firdes utility to build the filter, we build a
+ * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB
+ * bandwidth of <EM>BW</EM> and a transition bandwidth of
+ * <EM>TB</EM>. We can also specify the out-of-band attenuation to
+ * use, <EM>ATT</EM>, and the filter window function (a
+ * Blackman-harris window in this case). The first input is the
+ * gain of the filter, which we specify here as the interpolation
+ * rate (<EM>32</EM>).
+ *
+ * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB,
+ * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B>
+ *
+ * The theory behind this block can be found in Chapter 7.5 of the
+ * following book.
+ *
+ * <B><EM>f. harris, "Multirate Signal Processing for Communication
+ * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B>
+ */
+
+ class FILTER_API pfb_arb_resampler_fff : virtual public gr_block
+ {
+ public:
+ // gr::filter::pfb_arb_resampler_fff::sptr
+ typedef boost::shared_ptr<pfb_arb_resampler_fff> sptr;
+
+ /*!
+ * Build the polyphase filterbank arbitray resampler.
+ * \param rate (float) Specifies the resampling rate to use
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps
+ * should be generated at the filter_size sampling rate.
+ * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly
+ * related to quantization noise introduced during the resampling.
+ * Defaults to 32 filters.
+ */
+ static FILTER_API sptr make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size=32);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param taps (vector/list of floats) The prototype filter to populate the filterbank.
+ */
+ virtual void set_taps(const std::vector<float> &taps) = 0;
+
+ /*!
+ * Return a vector<vector<>> of the filterbank taps
+ */
+ virtual std::vector<std::vector<float> > taps() const = 0;
+
+ /*!
+ * Print all of the filterbank taps to screen.
+ */
+ virtual void print_taps() = 0;
+
+ virtual void set_rate (float rate) = 0;
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_H */
diff --git a/gr-filter/include/filter/pfb_decimator_ccf.h b/gr-filter/include/filter/pfb_decimator_ccf.h
index e0b8dce15..e41f16cd2 100644
--- a/gr-filter/include/filter/pfb_decimator_ccf.h
+++ b/gr-filter/include/filter/pfb_decimator_ccf.h
@@ -128,4 +128,4 @@ namespace gr {
} /* namespace filter */
} /* namespace gr */
-#endif /* INCLUDED_FILTER_PFB_DECIMATOR_CCF_H */
+#endif /* INCLUDED_PFB_DECIMATOR_CCF_H */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index d1ddd2a92..8077baf9c 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -127,6 +127,8 @@ list(APPEND filter_sources
fractional_interpolator_ff_impl.cc
hilbert_fc_impl.cc
iir_filter_ffd_impl.cc
+ pfb_arb_resampler_ccf_impl.cc
+ pfb_arb_resampler_fff_impl.cc
pfb_channelizer_ccf_impl.cc
pfb_decimator_ccf_impl.cc
pfb_interpolator_ccf_impl.cc
diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc
new file mode 100644
index 000000000..bb0906aa5
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc
@@ -0,0 +1,235 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,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 "pfb_arb_resampler_ccf_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ pfb_arb_resampler_ccf::sptr
+ pfb_arb_resampler_ccf::make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_arb_resampler_ccf_impl(rate, taps, filter_size));
+ }
+
+
+ pfb_arb_resampler_ccf_impl::pfb_arb_resampler_ccf_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ : gr_block("pfb_arb_resampler_ccf",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ d_updated (false)
+ {
+ d_acc = 0; // start accumulator at 0
+
+ /* The number of filters is specified by the user as the filter
+ size; this is also the interpolation rate of the filter. We
+ use it and the rate provided to determine the decimation
+ rate. This acts as a rational resampler. The flt_rate is
+ calculated as the residual between the integer decimation
+ rate and the real decimation rate and will be used to
+ determine to interpolation point of the resampling process.
+ */
+ d_int_rate = filter_size;
+ set_rate(rate);
+
+ // Store the last filter between calls to work
+ d_last_filter = 0;
+
+ d_start_index = 0;
+
+ d_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate);
+ d_diff_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_int_rate);
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ d_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_diff_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ }
+
+ // Now, actually set the filters' taps
+ std::vector<float> dtaps;
+ create_diff_taps(taps, dtaps);
+ create_taps(taps, d_taps, d_filters);
+ create_taps(dtaps, d_dtaps, d_diff_filters);
+ }
+
+ pfb_arb_resampler_ccf_impl::~pfb_arb_resampler_ccf_impl()
+ {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ delete d_filters[i];
+ delete d_diff_filters[i];
+ }
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_ccf*> &ourfilter)
+ {
+ unsigned int ntaps = newtaps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
+
+ // Create d_numchan vectors to store each channel's taps
+ ourtaps.resize(d_int_rate);
+
+ // 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<float> tmp_taps;
+ tmp_taps = newtaps;
+ while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
+ for(unsigned int j = 0; j < d_taps_per_filter; j++) {
+ ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
+ }
+
+ // Set the history to ensure enough input items for each filter
+ set_history (d_taps_per_filter + 1);
+
+ d_updated = true;
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps)
+ {
+ // Calculate the differential taps (derivative filter) by taking the difference
+ // between two taps. Duplicate the last one to make both filters the same length.
+ float tap;
+ difftaps.clear();
+ for(unsigned int i = 0; i < newtaps.size()-1; i++) {
+ tap = newtaps[i+1] - newtaps[i];
+ difftaps.push_back(tap);
+ }
+ difftaps.push_back(tap);
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+ }
+
+ std::vector<std::vector<float> >
+ pfb_arb_resampler_ccf_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_int_rate; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n");
+ }
+ }
+
+ void
+ pfb_arb_resampler_ccf_impl::set_rate(float rate)
+ {
+ d_dec_rate = (unsigned int)floor(d_int_rate/rate);
+ d_flt_rate = (d_int_rate/rate) - d_dec_rate;
+ set_relative_rate(rate);
+ }
+
+ int
+ pfb_arb_resampler_ccf_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_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.
+ }
+
+ int i = 0, count = d_start_index;
+ unsigned int j;
+ gr_complex o0, o1;
+
+ // Restore the last filter position
+ j = d_last_filter;
+
+ // produce output as long as we can and there are enough input samples
+ int max_input = ninput_items[0] - (int)d_taps_per_filter;
+ while((i < noutput_items) && (count < max_input)) {
+ // start j by wrapping around mod the number of channels
+ while((j < d_int_rate) && (i < noutput_items)) {
+ // Take the current filter and derivative filter output
+ o0 = d_filters[j]->filter(&in[count]);
+ o1 = d_diff_filters[j]->filter(&in[count]);
+
+ out[i] = o0 + o1*d_acc; // linearly interpolate between samples
+ i++;
+
+ // Adjust accumulator and index into filterbank
+ d_acc += d_flt_rate;
+ j += d_dec_rate + (int)floor(d_acc);
+ d_acc = fmodf(d_acc, 1.0);
+ }
+ if(i < noutput_items) { // keep state for next entry
+ float ss = (int)(j / d_int_rate); // number of items to skip ahead by
+ count += ss; // we have fully consumed another input
+ j = j % d_int_rate; // roll filter around
+ }
+ }
+
+ // Store the current filter position and start of next sample
+ d_last_filter = j;
+ d_start_index = std::max(0, count - ninput_items[0]);
+
+ // consume all we've processed but no more than we can
+ consume_each(std::min(count, ninput_items[0]));
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.h b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h
new file mode 100644
index 000000000..8e7e993cb
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009,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_PFB_ARB_RESAMPLER_CCF_IMPL_H
+#define INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H
+
+#include <filter/pfb_arb_resampler_ccf.h>
+#include <filter/fir_filter.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_arb_resampler_ccf_impl : public pfb_arb_resampler_ccf
+ {
+ private:
+ std::vector<kernel::fir_filter_ccf*> d_filters;
+ std::vector<kernel::fir_filter_ccf*> d_diff_filters;
+ std::vector< std::vector<float> > d_taps;
+ std::vector< std::vector<float> > d_dtaps;
+ unsigned int d_int_rate; // the number of filters (interpolation rate)
+ unsigned int d_dec_rate; // the stride through the filters (decimation rate)
+ float d_flt_rate; // residual rate for the linear interpolation
+ float d_acc;
+ unsigned int d_last_filter;
+ int d_start_index;
+ unsigned int d_taps_per_filter;
+ bool d_updated;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ void create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
+ * The taps should be generated at the interpolated sampling rate.
+ * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
+ * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
+ */
+ void create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_ccf*> &ourfilter);
+
+ public:
+ pfb_arb_resampler_ccf_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size);
+
+ ~pfb_arb_resampler_ccf_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<std::vector<float> > taps() const;
+ void print_taps();
+ void set_rate(float rate);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H */
diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.cc b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc
new file mode 100644
index 000000000..79c19655a
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc
@@ -0,0 +1,237 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-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 "pfb_arb_resampler_fff_impl.h"
+#include <gr_io_signature.h>
+#include <cstdio>
+
+namespace gr {
+ namespace filter {
+
+ pfb_arb_resampler_fff::sptr
+ pfb_arb_resampler_fff::make(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ {
+ return gnuradio::get_initial_sptr
+ (new pfb_arb_resampler_fff_impl(rate, taps, filter_size));
+ }
+
+
+ pfb_arb_resampler_fff_impl::pfb_arb_resampler_fff_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size)
+ : gr_block("pfb_arb_resampler_fff",
+ gr_make_io_signature(1, 1, sizeof(float)),
+ gr_make_io_signature(1, 1, sizeof(float))),
+ d_updated(false)
+ {
+ d_acc = 0; // start accumulator at 0
+
+ /* The number of filters is specified by the user as the filter
+ size; this is also the interpolation rate of the filter. We
+ use it and the rate provided to determine the decimation
+ rate. This acts as a rational resampler. The flt_rate is
+ calculated as the residual between the integer decimation
+ rate and the real decimation rate and will be used to
+ determine to interpolation point of the resampling process.
+ */
+ d_int_rate = filter_size;
+ set_rate(rate);
+
+ // Store the last filter between calls to work
+ d_last_filter = 0;
+
+ d_start_index = 0;
+
+ d_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate);
+ d_diff_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_int_rate);
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ d_filters[i] = new kernel::fir_filter_fff(1, vtaps);
+ d_diff_filters[i] = new kernel::fir_filter_fff(1, vtaps);
+ }
+
+ // Now, actually set the filters' taps
+ std::vector<float> dtaps;
+ create_diff_taps(taps, dtaps);
+ create_taps(taps, d_taps, d_filters);
+ create_taps(dtaps, d_dtaps, d_diff_filters);
+ }
+
+ pfb_arb_resampler_fff_impl::~pfb_arb_resampler_fff_impl()
+ {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ delete d_filters[i];
+ delete d_diff_filters[i];
+ }
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_fff*> &ourfilter)
+ {
+ unsigned int ntaps = newtaps.size();
+ d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
+
+ // Create d_numchan vectors to store each channel's taps
+ ourtaps.resize(d_int_rate);
+
+ // 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<float> tmp_taps;
+ tmp_taps = newtaps;
+ while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) {
+ tmp_taps.push_back(0.0);
+ }
+
+ // Partition the filter
+ for(unsigned int i = 0; i < d_int_rate; i++) {
+ // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+ ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
+ for(unsigned int j = 0; j < d_taps_per_filter; j++) {
+ ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
+ }
+
+ // Build a filter for each channel and add it's taps to it
+ ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]);
+ }
+
+ // Set the history to ensure enough input items for each filter
+ set_history(d_taps_per_filter + 1);
+
+ d_updated = true;
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps)
+ {
+ // Calculate the differential taps (derivative filter) by taking the difference
+ // between two taps. Duplicate the last one to make both filters the same length.
+ float tap;
+ difftaps.clear();
+ for(unsigned int i = 0; i < newtaps.size()-1; i++) {
+ tap = newtaps[i+1] - newtaps[i];
+ difftaps.push_back(tap);
+ }
+ difftaps.push_back(tap);
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::set_taps(const std::vector<float> &taps)
+ {
+ gruel::scoped_lock guard(d_mutex);
+ }
+
+ std::vector<std::vector<float> >
+ pfb_arb_resampler_fff_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::print_taps()
+ {
+ unsigned int i, j;
+ for(i = 0; i < d_int_rate; i++) {
+ printf("filter[%d]: [", i);
+ for(j = 0; j < d_taps_per_filter; j++) {
+ printf(" %.4e", d_taps[i][j]);
+ }
+ printf("]\n");
+ }
+ }
+
+ void
+ pfb_arb_resampler_fff_impl::set_rate(float rate)
+ {
+ d_dec_rate = (unsigned int)floor(d_int_rate/rate);
+ d_flt_rate = (d_int_rate/rate) - d_dec_rate;
+ set_relative_rate(rate);
+ }
+
+ int
+ pfb_arb_resampler_fff_impl::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gruel::scoped_lock guard(d_mutex);
+
+ float *in = (float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ if(d_updated) {
+ d_updated = false;
+ return 0; // history requirements may have changed.
+ }
+
+ int i = 0, count = d_start_index;
+ unsigned int j;
+ float o0, o1;
+
+ // Restore the last filter position
+ j = d_last_filter;
+
+ // produce output as long as we can and there are enough input samples
+ int max_input = ninput_items[0] - (int)d_taps_per_filter;
+ while((i < noutput_items) && (count < max_input)) {
+ // start j by wrapping around mod the number of channels
+ while((j < d_int_rate) && (i < noutput_items)) {
+ // Take the current filter and derivative filter output
+ o0 = d_filters[j]->filter(&in[count]);
+ o1 = d_diff_filters[j]->filter(&in[count]);
+
+ out[i] = o0 + o1*d_acc; // linearly interpolate between samples
+ i++;
+
+ // Adjust accumulator and index into filterbank
+ d_acc += d_flt_rate;
+ j += d_dec_rate + (int)floor(d_acc);
+ d_acc = fmodf(d_acc, 1.0);
+ }
+ if(i < noutput_items) { // keep state for next entry
+ float ss = (int)(j / d_int_rate); // number of items to skip ahead by
+ count += ss; // we have fully consumed another input
+ j = j % d_int_rate; // roll filter around
+ }
+ }
+
+ // Store the current filter position and start of next sample
+ d_last_filter = j;
+ d_start_index = std::max(0, count - ninput_items[0]);
+
+ // consume all we've processed but no more than we can
+ consume_each(std::min(count, ninput_items[0]));
+ return i;
+ }
+
+ } /* namespace filter */
+} /* namespace gr */
diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.h b/gr-filter/lib/pfb_arb_resampler_fff_impl.h
new file mode 100644
index 000000000..54e01375a
--- /dev/null
+++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009-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_PFB_ARB_RESAMPLER_FFF_IMPL_H
+#define INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H
+
+#include <filter/pfb_arb_resampler_fff.h>
+#include <filter/fir_filter.h>
+#include <gruel/thread.h>
+
+namespace gr {
+ namespace filter {
+
+ class FILTER_API pfb_arb_resampler_fff_impl : public pfb_arb_resampler_fff
+ {
+ private:
+ std::vector<kernel::fir_filter_fff*> d_filters;
+ std::vector<kernel::fir_filter_fff*> d_diff_filters;
+ std::vector< std::vector<float> > d_taps;
+ std::vector< std::vector<float> > d_dtaps;
+ unsigned int d_int_rate; // the number of filters (interpolation rate)
+ unsigned int d_dec_rate; // the stride through the filters (decimation rate)
+ float d_flt_rate; // residual rate for the linear interpolation
+ float d_acc;
+ unsigned int d_last_filter;
+ int d_start_index;
+ unsigned int d_taps_per_filter;
+ bool d_updated;
+ gruel::mutex d_mutex; // mutex to protect set/work access
+
+ void create_diff_taps(const std::vector<float> &newtaps,
+ std::vector<float> &difftaps);
+
+ /*!
+ * Resets the filterbank's filter taps with the new prototype filter
+ * \param newtaps (vector of floats) The prototype filter to populate the filterbank.
+ * The taps should be generated at the interpolated sampling rate.
+ * \param ourtaps (vector of floats) Reference to our internal member of holding the taps.
+ * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for.
+ */
+ void create_taps(const std::vector<float> &newtaps,
+ std::vector< std::vector<float> > &ourtaps,
+ std::vector<kernel::fir_filter_fff*> &ourfilter);
+ public:
+ pfb_arb_resampler_fff_impl(float rate,
+ const std::vector<float> &taps,
+ unsigned int filter_size);
+
+ ~pfb_arb_resampler_fff_impl();
+
+ void set_taps(const std::vector<float> &taps);
+ std::vector<std::vector<float> > taps() const;
+ void print_taps();
+ void set_rate(float rate);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace filter */
+} /* namespace gr */
+
+#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H */
diff --git a/gr-filter/python/qa_pfb_arb_resampler.py b/gr-filter/python/qa_pfb_arb_resampler.py
new file mode 100755
index 000000000..655b680f0
--- /dev/null
+++ b/gr-filter/python/qa_pfb_arb_resampler.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+from gnuradio import gr, gr_unittest
+import filter_swig as filter
+import math
+
+class test_pfb_arb_resampler(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_fff_000(self):
+ N = 1000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ nfilts = 32
+ taps = gr.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=gr.firdes.WIN_BLACKMAN_hARRIS)
+
+ freq = 100
+ signal = gr.sig_source_f(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_float, N)
+ pfb = filter.pfb_arb_resampler_fff(rrate, taps)
+ snk = gr.vector_sink_f()
+
+ self.tb.connect(signal, head, pfb, snk)
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs*rrate), xrange(L))
+
+ phase = 0.53013
+ expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+ self.assertFloatTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+ def test_ccf_000(self):
+ N = 1000 # number of samples to use
+ fs = 1000 # baseband sampling rate
+ rrate = 1.123 # resampling rate
+
+ nfilts = 32
+ taps = gr.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
+ attenuation_dB=80,
+ window=gr.firdes.WIN_BLACKMAN_hARRIS)
+
+ freq = 100
+ signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1)
+ head = gr.head(gr.sizeof_gr_complex, N)
+ pfb = filter.pfb_arb_resampler_ccf(rrate, taps)
+ snk = gr.vector_sink_c()
+
+ self.tb.connect(signal, head, pfb, snk)
+ self.tb.run()
+
+ Ntest = 50
+ L = len(snk.data())
+ t = map(lambda x: float(x)/(fs*rrate), xrange(L))
+
+ phase = 0.53013
+ expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
+ 1j*math.sin(2.*math.pi*freq*x+phase), t)
+
+ dst_data = snk.data()
+ self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_pfb_arb_resampler, "test_pfb_arb_resampler.xml")
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index cc2e51d96..b72a67f15 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -59,6 +59,8 @@
#include "filter/interp_fir_filter_fff.h"
#include "filter/interp_fir_filter_fsf.h"
#include "filter/interp_fir_filter_scc.h"
+#include "filter/pfb_arb_resampler_ccf.h"
+#include "filter/pfb_arb_resampler_fff.h"
#include "filter/pfb_channelizer_ccf.h"
#include "filter/pfb_decimator_ccf.h"
#include "filter/pfb_interpolator_ccf.h"
@@ -97,6 +99,8 @@
%include "filter/interp_fir_filter_fff.h"
%include "filter/interp_fir_filter_fsf.h"
%include "filter/interp_fir_filter_scc.h"
+%include "filter/pfb_arb_resampler_ccf.h"
+%include "filter/pfb_arb_resampler_fff.h"
%include "filter/pfb_channelizer_ccf.h"
%include "filter/pfb_decimator_ccf.h"
%include "filter/pfb_interpolator_ccf.h"
@@ -132,6 +136,8 @@ GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fcc);
GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fff);
GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fsf);
GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_scc);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_ccf);
+GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_fff);
GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, pfb_decimator_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, pfb_interpolator_ccf);