[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 04/06: filter: use fft_filter inside pfb_de
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 04/06: filter: use fft_filter inside pfb_decimator. |
Date: |
Fri, 28 Feb 2014 16:53:15 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
trondeau pushed a commit to branch master
in repository gnuradio.
commit 22ab16842e30ca9280e62415754018a0d521acb1
Author: Tom Rondeau <address@hidden>
Date: Wed Feb 26 15:02:05 2014 -0500
filter: use fft_filter inside pfb_decimator.
Depending on the decimation rate and filter size, filtering with time
domain or freq domain can be slower/faster and rotating using expj or fft can
be slower/faster. This enables users to decide which features to use.
---
gr-filter/grc/filter_pfb_decimator.xml | 34 +++-
.../include/gnuradio/filter/pfb_decimator_ccf.h | 13 +-
.../include/gnuradio/filter/polyphase_filterbank.h | 12 +-
gr-filter/lib/pfb_decimator_ccf_impl.cc | 183 +++++++++++++++++----
gr-filter/lib/pfb_decimator_ccf_impl.h | 26 ++-
gr-filter/lib/pfb_interpolator_ccf_impl.cc | 4 +-
gr-filter/lib/polyphase_filterbank.cc | 31 ++--
gr-filter/python/filter/pfb.py | 12 +-
gr-filter/python/filter/qa_pfb_decimator.py | 66 ++++++--
9 files changed, 298 insertions(+), 83 deletions(-)
diff --git a/gr-filter/grc/filter_pfb_decimator.xml
b/gr-filter/grc/filter_pfb_decimator.xml
index d571196..3a82876 100644
--- a/gr-filter/grc/filter_pfb_decimator.xml
+++ b/gr-filter/grc/filter_pfb_decimator.xml
@@ -13,7 +13,9 @@
$decim,
$taps,
$channel,
- $atten)
+ $atten,
+ $fft_rot,
+ $fft_filts)
</make>
<callback>set_taps($taps)</callback>
<callback>set_channel(int($channel))</callback>
@@ -40,6 +42,36 @@
<value>100</value>
<type>real</type>
</param>
+ <param>
+ <name>Use FFT Rotator</name>
+ <key>fft_rot</key>
+ <value>True</value>
+ <type>raw</type>
+ <hide>part</hide>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
+ <param>
+ <name>Use FFT Filters</name>
+ <key>fft_filts</key>
+ <value>True</value>
+ <type>raw</type>
+ <hide>part</hide>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
diff --git a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
index da4eb2b..06f329a 100644
--- a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
@@ -99,10 +99,19 @@ namespace gr {
* \param decim (unsigned integer) Specifies the decimation rate to use
* \param taps (vector/list of floats) The prototype filter to
populate the filterbank.
* \param channel (unsigned integer) Selects the channel to return
[default=0].
+ * \param use_fft_rotator (bool) Rotate channels using FFT method
instead of exp(phi).
+ * For larger values of \p channel, the FFT method will
perform better.
+ * Generally, this value of \p channel is small (~5), but
could be
+ * architecture-specific (Default: true).
+ * \param use_fft_filters (bool) Use FFT filters (fast convolution)
instead of FIR filters.
+ * FFT filters perform better for larger numbers of taps
but is
+ * architecture-specific (Default: true).
*/
static sptr make(unsigned int decim,
- const std::vector<float> &taps,
- unsigned int channel);
+ const std::vector<float> &taps,
+ unsigned int channel,
+ bool use_fft_rotator=true,
+ bool use_fft_filters=true);
/*!
* Resets the filterbank's filter taps with the new prototype filter
diff --git a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
index fad04e3..1745a47 100644
--- a/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
+++ b/gr-filter/include/gnuradio/filter/polyphase_filterbank.h
@@ -26,6 +26,7 @@
#include <gnuradio/filter/api.h>
#include <gnuradio/filter/fir_filter.h>
+#include <gnuradio/filter/fft_filter.h>
#include <gnuradio/fft/fft.h>
namespace gr {
@@ -101,11 +102,12 @@ namespace gr {
{
protected:
unsigned int d_nfilts;
- std::vector<kernel::fir_filter_ccf*> d_filters;
+ std::vector<kernel::fir_filter_ccf*> d_fir_filters;
+ std::vector<kernel::fft_filter_ccf*> d_fft_filters;
std::vector< std::vector<float> > d_taps;
unsigned int d_taps_per_filter;
fft::fft_complex *d_fft;
-
+
public:
/*!
* Build the polyphase filterbank decimator.
@@ -113,9 +115,11 @@ namespace gr {
* channels <EM>M</EM>
* \param taps (vector/list of floats) The prototype filter to
* populate the filterbank.
+ * \param fft_forward (bool) use a forward or inverse FFT
(default=false).
*/
polyphase_filterbank(unsigned int nfilts,
- const std::vector<float> &taps);
+ const std::vector<float> &taps,
+ bool fft_forward=false);
~polyphase_filterbank();
@@ -126,7 +130,7 @@ namespace gr {
* \param taps (vector/list of floats) The prototype filter to
* populate the filterbank.
*/
- void set_taps(const std::vector<float> &taps);
+ virtual void set_taps(const std::vector<float> &taps);
/*!
* Print all of the filterbank taps to screen.
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc
b/gr-filter/lib/pfb_decimator_ccf_impl.cc
index 19cf20f..7b4bf73 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2009,2010,2012 Free Software Foundation, Inc.
+ * Copyright 2009,2010,2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,34 +26,53 @@
#include "pfb_decimator_ccf_impl.h"
#include <gnuradio/io_signature.h>
+#include <gnuradio/expj.h>
+#include <volk/volk.h>
namespace gr {
namespace filter {
-
+
pfb_decimator_ccf::sptr
pfb_decimator_ccf::make(unsigned int decim,
const std::vector<float> &taps,
- unsigned int channel)
+ unsigned int channel,
+ bool use_fft_rotator,
+ bool use_fft_filters)
{
return gnuradio::get_initial_sptr
- (new pfb_decimator_ccf_impl(decim, taps, channel));
+ (new pfb_decimator_ccf_impl(decim, taps, channel,
+ use_fft_rotator,
+ use_fft_filters));
}
-
pfb_decimator_ccf_impl::pfb_decimator_ccf_impl(unsigned int decim,
const std::vector<float>
&taps,
- unsigned int channel)
+ unsigned int channel,
+ bool use_fft_rotator,
+ bool use_fft_filters)
: sync_block("pfb_decimator_ccf",
- io_signature::make(decim, decim, sizeof(gr_complex)),
- io_signature::make(1, 1, sizeof(gr_complex))),
+ io_signature::make(decim, decim, sizeof(gr_complex)),
+ io_signature::make(1, 1, sizeof(gr_complex))),
polyphase_filterbank(decim, taps),
- d_updated(false), d_chan(channel)
+ d_updated(false), d_chan(channel),
+ d_use_fft_rotator(use_fft_rotator),
+ d_use_fft_filters(use_fft_filters)
{
d_rate = decim;
d_rotator = new gr_complex[d_rate];
+ for(unsigned int i = 0; i < d_rate; i++) {
+ d_rotator[i] = gr_expj(i*d_chan*2*M_PI/d_rate);
+ }
set_relative_rate(1.0/(float)decim);
- set_history(d_taps_per_filter);
+
+ if(d_use_fft_filters) {
+ set_history(1);
+ set_output_multiple(d_fft_filters[0]->filtersize() -
d_fft_filters[0]->ntaps() + 1);
+ }
+ else {
+ set_history(d_taps_per_filter);
+ }
}
pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl()
@@ -90,8 +109,6 @@ namespace gr {
d_chan = chan;
}
-#define ROTATEFFT
-
int
pfb_decimator_ccf_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
@@ -99,47 +116,145 @@ namespace gr {
{
gr::thread::scoped_lock guard(d_mutex);
- gr_complex *in;
- gr_complex *out = (gr_complex *)output_items[0];
-
if(d_updated) {
d_updated = false;
return 0; // history requirements may have changed.
}
+ if(d_use_fft_rotator) {
+ if(d_use_fft_filters) {
+ return work_fft_fft(noutput_items, input_items, output_items);
+ }
+ else {
+ return work_fir_fft(noutput_items, input_items, output_items);
+ }
+ }
+ else {
+ if(d_use_fft_filters) {
+ return work_fft_exp(noutput_items, input_items, output_items);
+ }
+ else {
+ return work_fir_exp(noutput_items, input_items, output_items);
+ }
+ }
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fir_exp(int noutput_items,
+ gr_vector_const_void_star
&input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
int i;
for(i = 0; i < noutput_items; i++) {
// Move through filters from bottom to top
out[i] = 0;
for(int j = d_rate-1; j >= 0; j--) {
- // Take in the items from the first input stream to d_rate
+ // Take items from M-1 to 0; filter and rotate
in = (gr_complex*)input_items[d_rate - 1 - j];
+ out[i] += d_fir_filters[j]->filter(&in[i])*d_rotator[j];
+ }
+ }
- // Filter current input stream from bottom filter to top
- // The rotate them by expj(j*k*2pi/M) where M is the number of filters
- // (the decimation rate) and k is the channel number to extract
-
- // This is the real math that goes on; we abuse the FFT to do this
quickly
- // for decimation rates > N where N is a small number (~5):
- // out[i] +=
d_filters[j]->filter(&in[i])*gr_expj(j*d_chan*2*M_PI/d_rate);
-#ifdef ROTATEFFT
- d_fft->get_inbuf()[j] = d_filters[j]->filter(&in[i]);
-#else
- out[i] += d_filters[j]->filter(&in[i])*d_rotator[i];
-#endif
+ return noutput_items;
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fir_fft(int noutput_items,
+ gr_vector_const_void_star
&input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ for(i = 0; i < noutput_items; i++) {
+ // Move through filters from bottom to top
+ out[i] = 0;
+ for(unsigned int j = 0; j < d_rate; j++) {
+ // Take in the items from the first input stream to d_rate
+ in = (gr_complex*)input_items[d_rate-1-j];
+ d_fft->get_inbuf()[j] = d_fir_filters[j]->filter(&in[i]);
}
-#ifdef ROTATEFFT
- // Perform the FFT to do the complex multiply despinning for all
channels
- d_fft->execute();
+ // Perform the FFT to do the complex multiply despinning for all
channels
+ d_fft->execute();
- // Select only the desired channel out
- out[i] = d_fft->get_outbuf()[d_chan];
-#endif
+ // Select only the desired channel out
+ out[i] = d_fft->get_outbuf()[d_chan];
+ }
+
+ return noutput_items;
+ }
+
+ int
+ pfb_decimator_ccf_impl::work_fft_exp(int noutput_items,
+ gr_vector_const_void_star
&input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
+
+ // Filter each input stream by the FFT filters; do all
+ // noutput_items at once to avoid repeated calls to the FFT
+ // setup and operation.
+ for(unsigned int j = 0; j < d_rate; j++) {
+ in = (gr_complex*)input_items[d_rate-j-1];
+ d_fft_filters[j]->filter(noutput_items, in, &(tmp[j*noutput_items]));
+ }
+
+ // Rotate and add filter outputs (k=channel number; M=number of
+ // channels; and x[j] is the output of filter j.
+ // y[i] = \sum_{j=0}{M-1} (x[j][i]*exp(2j \pi j k / M))
+ for(i = 0; i < noutput_items; i++) {
+ out[i] = 0;
+ for(unsigned int j = 0; j < d_rate; j++) {
+ out[i] += tmp[j*noutput_items+i]*d_rotator[j];
+ }
}
return noutput_items;
}
+ int
+ pfb_decimator_ccf_impl::work_fft_fft(int noutput_items,
+ gr_vector_const_void_star
&input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *in;
+ gr_complex *out = (gr_complex *)output_items[0];
+
+ int i;
+ gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
+
+ for(unsigned int j = 0; j < d_rate; j++) {
+ in = (gr_complex*)input_items[d_rate-j-1];
+ d_fft_filters[j]->filter(noutput_items, in, &tmp[j*noutput_items]);
+ }
+
+ // Performs the rotate and add operations by implementing it as
+ // an FFT.
+ for(i = 0; i < noutput_items; i++) {
+ for(unsigned int j = 0; j < d_rate; j++) {
+ d_fft->get_inbuf()[j] = tmp[j*noutput_items + i];
+ }
+
+ // Perform the FFT to do the complex multiply despinning for all
channels
+ d_fft->execute();
+
+ // Select only the desired channel out
+ out[i] = d_fft->get_outbuf()[d_chan];
+ }
+
+ fft::free(tmp);
+ return noutput_items;
+ }
+
+
} /* namespace filter */
} /* namespace gr */
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h
b/gr-filter/lib/pfb_decimator_ccf_impl.h
index 2df8a50..3397701 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.h
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.h
@@ -26,26 +26,42 @@
#include <gnuradio/filter/pfb_decimator_ccf.h>
#include <gnuradio/filter/polyphase_filterbank.h>
-#include <gnuradio/filter/fir_filter.h>
-#include <gnuradio/fft/fft.h>
#include <gnuradio/thread/thread.h>
namespace gr {
namespace filter {
-
+
class FILTER_API pfb_decimator_ccf_impl : public pfb_decimator_ccf,
kernel::polyphase_filterbank
{
private:
bool d_updated;
unsigned int d_rate;
unsigned int d_chan;
+ bool d_use_fft_rotator;
+ bool d_use_fft_filters;
gr_complex *d_rotator;
gr::thread::mutex d_mutex; // mutex to protect set/work access
-
+
+ inline int work_fir_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fir_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fft_exp(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ inline int work_fft_fft(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+
public:
pfb_decimator_ccf_impl(unsigned int decim,
const std::vector<float> &taps,
- unsigned int channel);
+ unsigned int channel,
+ bool use_fft_rotator=true,
+ bool use_fft_filters=true);
~pfb_decimator_ccf_impl();
diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.cc
b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
index a0ed73f..cf79c10 100644
--- a/gr-filter/lib/pfb_interpolator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_interpolator_ccf_impl.cc
@@ -29,7 +29,7 @@
namespace gr {
namespace filter {
-
+
pfb_interpolator_ccf::sptr
pfb_interpolator_ccf::make(unsigned int interp,
const std::vector<float> &taps)
@@ -94,7 +94,7 @@ namespace gr {
while(i < noutput_items) {
for(unsigned int j = 0; j < d_rate; j++) {
- out[i] = d_filters[j]->filter(&in[count]);
+ out[i] = d_fir_filters[j]->filter(&in[count]);
i++;
}
count++;
diff --git a/gr-filter/lib/polyphase_filterbank.cc
b/gr-filter/lib/polyphase_filterbank.cc
index ab978e8..ac20eb4 100644
--- a/gr-filter/lib/polyphase_filterbank.cc
+++ b/gr-filter/lib/polyphase_filterbank.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,29 +32,33 @@ namespace gr {
namespace kernel {
polyphase_filterbank::polyphase_filterbank(unsigned int nfilts,
- const std::vector<float> &taps)
+ const std::vector<float> &taps,
+ bool fft_forward)
: d_nfilts(nfilts)
{
- d_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts);
+ d_fir_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts);
+ d_fft_filters = std::vector<kernel::fft_filter_ccf*>(d_nfilts);
// Create an FIR filter for each channel and zero out the taps
- std::vector<float> vtaps(0, d_nfilts);
+ std::vector<float> vtaps(1, 0.0f);
for(unsigned int i = 0; i < d_nfilts; i++) {
- d_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_fir_filters[i] = new kernel::fir_filter_ccf(1, vtaps);
+ d_fft_filters[i] = new kernel::fft_filter_ccf(1, vtaps);
}
// Now, actually set the filters' taps
set_taps(taps);
// Create the FFT to handle the output de-spinning of the channels
- d_fft = new fft::fft_complex(d_nfilts, false);
+ d_fft = new fft::fft_complex(d_nfilts, fft_forward);
}
polyphase_filterbank::~polyphase_filterbank()
{
delete d_fft;
for(unsigned int i = 0; i < d_nfilts; i++) {
- delete d_filters[i];
+ delete d_fir_filters[i];
+ delete d_fft_filters[i];
}
}
@@ -62,7 +66,6 @@ namespace gr {
polyphase_filterbank::set_taps(const std::vector<float> &taps)
{
unsigned int i,j;
-
unsigned int ntaps = taps.size();
d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilts);
@@ -71,14 +74,11 @@ namespace gr {
// 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 = taps;
+ std::vector<float> tmp_taps = taps;
while((float)(tmp_taps.size()) < d_nfilts*d_taps_per_filter) {
- tmp_taps.push_back(0.0);
+ tmp_taps.push_back(0.0);
}
- // Reverse taps here; set_taps in filter will then re-reverse,
- // but order them propely, anyways.
std::reverse(tmp_taps.begin(), tmp_taps.end());
// Partition the filter
@@ -89,8 +89,9 @@ namespace gr {
d_taps[i][j] = tmp_taps[i + j*d_nfilts];
}
- // Build a filter for each channel and add it's taps to it
- d_filters[i]->set_taps(d_taps[i]);
+ // Set the filter taps for each channel
+ d_fir_filters[i]->set_taps(d_taps[i]);
+ d_fft_filters[i]->set_taps(d_taps[i]);
}
}
diff --git a/gr-filter/python/filter/pfb.py b/gr-filter/python/filter/pfb.py
index 2ddf659..0ee0136 100644
--- a/gr-filter/python/filter/pfb.py
+++ b/gr-filter/python/filter/pfb.py
@@ -77,7 +77,11 @@ class channelizer_ccf(gr.hier_block2):
def set_channel_map(self, newmap):
self.pfb.set_channel_map(newmap)
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
+ def taps(self):
+ return self.pfb.taps()
class interpolator_ccf(gr.hier_block2):
'''
@@ -122,6 +126,8 @@ class interpolator_ccf(gr.hier_block2):
self.connect(self, self.pfb)
self.connect(self.pfb, self)
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
class decimator_ccf(gr.hier_block2):
'''
@@ -130,7 +136,8 @@ class decimator_ccf(gr.hier_block2):
This simplifies the interface by allowing a single input stream to connect
to this block.
It will then output a stream that is the decimated output stream.
'''
- def __init__(self, decim, taps=None, channel=0, atten=100):
+ def __init__(self, decim, taps=None, channel=0, atten=100,
+ use_fft_rotators=True, use_fft_filters=True):
gr.hier_block2.__init__(self, "pfb_decimator_ccf",
gr.io_signature(1, 1, gr.sizeof_gr_complex),
gr.io_signature(1, 1, gr.sizeof_gr_complex))
@@ -160,7 +167,8 @@ class decimator_ccf(gr.hier_block2):
raise RuntimeError("optfir could not generate an
appropriate filter.")
self.s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, self._decim)
- self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps,
self._channel)
+ self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps,
self._channel,
+ use_fft_rotators, use_fft_filters)
self.connect(self, self.s2ss)
diff --git a/gr-filter/python/filter/qa_pfb_decimator.py
b/gr-filter/python/filter/qa_pfb_decimator.py
index ea7a155..745ee53 100755
--- a/gr-filter/python/filter/qa_pfb_decimator.py
+++ b/gr-filter/python/filter/qa_pfb_decimator.py
@@ -29,7 +29,7 @@ def sig_source_c(samp_rate, freq, amp, N):
1j*math.sin(2.*math.pi*freq*x), t)
return y
-def run_test(tb, channel):
+def run_test(tb, channel, fft_rotate, fft_filter):
N = 1000 # number of samples to use
M = 5 # Number of channels
fs = 5000.0 # baseband sampling rate
@@ -50,14 +50,14 @@ def run_test(tb, channel):
tb.connect(signals[i], (add,i))
s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M)
- pfb = filter.pfb_decimator_ccf(M, taps, channel)
+ pfb = filter.pfb_decimator_ccf(M, taps, channel, fft_rotate,
fft_filter)
snk = blocks.vector_sink_c()
tb.connect(add, s2ss)
for i in xrange(M):
tb.connect((s2ss,i), (pfb,i))
tb.connect(pfb, snk)
- tb.run()
+ tb.run()
L = len(snk.data())
@@ -90,33 +90,63 @@ class test_pfb_decimator(gr_unittest.TestCase):
def test_000(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 0)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 0, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 0, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 0, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 0, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:],
dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:],
dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:],
dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:],
dst_data3[-Ntest:], 4)
def test_001(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 1)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 1, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 1, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 1, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 1, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:],
dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:],
dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:],
dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:],
dst_data3[-Ntest:], 4)
def test_002(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 2)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 2, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 2, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 2, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 2, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:],
dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:],
dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:],
dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:],
dst_data3[-Ntest:], 4)
def test_003(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 3)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 3, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 3, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 3, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 3, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:],
dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:],
dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:],
dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:],
dst_data3[-Ntest:], 4)
def test_004(self):
Ntest = 50
- dst_data, expected_data = run_test(self.tb, 4)
-
- self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
dst_data[-Ntest:], 4)
+ dst_data0, expected_data0 = run_test(self.tb, 4, False, False)
+ dst_data1, expected_data1 = run_test(self.tb, 4, False, True)
+ dst_data2, expected_data2 = run_test(self.tb, 4, True, False)
+ dst_data3, expected_data3 = run_test(self.tb, 4, True, True)
+
+ self.assertComplexTuplesAlmostEqual(expected_data0[-Ntest:],
dst_data0[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data1[-Ntest:],
dst_data1[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data2[-Ntest:],
dst_data2[-Ntest:], 4)
+ self.assertComplexTuplesAlmostEqual(expected_data3[-Ntest:],
dst_data3[-Ntest:], 4)
if __name__ == '__main__':
gr_unittest.run(test_pfb_decimator, "test_pfb_decimator.xml")
- [Commit-gnuradio] [gnuradio] branch master updated (67882ee -> 103ca46), git, 2014/02/28
- [Commit-gnuradio] [gnuradio] 01/06: blocks: allow subtract block to take a single input to invert the sign., git, 2014/02/28
- [Commit-gnuradio] [gnuradio] 06/06: Merge branch 'pfb_reconstruction', git, 2014/02/28
- [Commit-gnuradio] [gnuradio] 02/06: blocks: allows null source/sink to output/input multiple streams., git, 2014/02/28
- [Commit-gnuradio] [gnuradio] 04/06: filter: use fft_filter inside pfb_decimator.,
git <=
- [Commit-gnuradio] [gnuradio] 05/06: filters: fixing up some minor issues with the analysis/synthesis filterbanks., git, 2014/02/28
- [Commit-gnuradio] [gnuradio] 03/06: filter: adds a ccf version of the fft filter., git, 2014/02/28