summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib
diff options
context:
space:
mode:
authorTom Rondeau2010-11-16 07:56:14 -0800
committerTom Rondeau2010-11-16 07:56:14 -0800
commit559d397de9ba937f470d27a7ad8b8d15f8f2f90f (patch)
tree221f32c0c10e55f9072fb22623e01fcd1dd63353 /gnuradio-core/src/lib
parenta6b5781e36ff75adb1e4d39d755d4ab8f5efd9dd (diff)
parent53eee1c624794056fcba50a5eb50b864cbf159dd (diff)
downloadgnuradio-559d397de9ba937f470d27a7ad8b8d15f8f2f90f.tar.gz
gnuradio-559d397de9ba937f470d27a7ad8b8d15f8f2f90f.tar.bz2
gnuradio-559d397de9ba937f470d27a7ad8b8d15f8f2f90f.zip
Merge branch 'next' into tagging
Diffstat (limited to 'gnuradio-core/src/lib')
-rw-r--r--gnuradio-core/src/lib/filter/.gitignore12
-rw-r--r--gnuradio-core/src/lib/filter/Makefile.am27
-rw-r--r--gnuradio-core/src/lib/filter/Makefile.gen17
-rw-r--r--gnuradio-core/src/lib/filter/filter.i2
-rwxr-xr-xgnuradio-core/src/lib/filter/generate_all.py2
-rwxr-xr-xgnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py64
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc1
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc169
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h98
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.i38
-rw-r--r--gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t121
-rw-r--r--gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t131
-rw-r--r--gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h131
-rw-r--r--gnuradio-core/src/lib/filter/qa_filter.cc12
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc160
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h46
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc167
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h46
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc168
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h46
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc156
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h46
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc147
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h46
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc167
-rw-r--r--gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h46
-rw-r--r--gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc5
-rw-r--r--gnuradio-core/src/lib/runtime/Makefile.am4
-rw-r--r--gnuradio-core/src/lib/swig/Makefile.am4
29 files changed, 2066 insertions, 13 deletions
diff --git a/gnuradio-core/src/lib/filter/.gitignore b/gnuradio-core/src/lib/filter/.gitignore
index 2d009f154..faaf02cb8 100644
--- a/gnuradio-core/src/lib/filter/.gitignore
+++ b/gnuradio-core/src/lib/filter/.gitignore
@@ -211,4 +211,16 @@
/gr_rational_resampler_base_scc.cc
/gr_rational_resampler_base_scc.h
/gr_rational_resampler_base_scc.i
+/gri_fir_filter_with_buffer_ccc.cc
+/gri_fir_filter_with_buffer_ccc.h
+/gri_fir_filter_with_buffer_ccf.cc
+/gri_fir_filter_with_buffer_ccf.h
+/gri_fir_filter_with_buffer_fcc.cc
+/gri_fir_filter_with_buffer_fcc.h
+/gri_fir_filter_with_buffer_fff.cc
+/gri_fir_filter_with_buffer_fff.h
+/gri_fir_filter_with_buffer_fsf.cc
+/gri_fir_filter_with_buffer_fsf.h
+/gri_fir_filter_with_buffer_scc.cc
+/gri_fir_filter_with_buffer_scc.h
/stamp-*
diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am
index 23c1dadc3..6d2ec1c7e 100644
--- a/gnuradio-core/src/lib/filter/Makefile.am
+++ b/gnuradio-core/src/lib/filter/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2001,2002,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+# Copyright 2001,2002,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -44,6 +44,7 @@ code_generator = \
generate_gr_fir_sysconfig_generic.py \
generate_gr_fir_util.py \
generate_gr_freq_xlating_fir_filter_XXX.py \
+ generate_gri_fir_filter_with_buffer_XXX.py \
generate_utils.py \
gr_fir_XXX.cc.t \
gr_fir_XXX.h.t \
@@ -60,7 +61,10 @@ code_generator = \
gr_rational_resampler_base_XXX.i.t \
gr_freq_xlating_fir_filter_XXX.cc.t \
gr_freq_xlating_fir_filter_XXX.h.t \
- gr_freq_xlating_fir_filter_XXX.i.t
+ gr_freq_xlating_fir_filter_XXX.i.t \
+ gri_fir_filter_with_buffer_XXX.cc.t \
+ gri_fir_filter_with_buffer_XXX.h.t
+
# Source built by Python into $(builddir)
BUILT_SOURCES = \
@@ -205,6 +209,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 \
@@ -220,7 +225,13 @@ libfilter_qa_la_common_SOURCES = \
qa_gr_fir_scc.cc \
qa_gr_rotator.cc \
qa_gri_mmse_fir_interpolator.cc \
- qa_gri_mmse_fir_interpolator_cc.cc
+ qa_gri_mmse_fir_interpolator_cc.cc \
+ qa_gri_fir_filter_with_buffer_ccf.cc \
+ qa_gri_fir_filter_with_buffer_ccc.cc \
+ qa_gri_fir_filter_with_buffer_fcc.cc \
+ qa_gri_fir_filter_with_buffer_fff.cc \
+ qa_gri_fir_filter_with_buffer_fsf.cc \
+ qa_gri_fir_filter_with_buffer_scc.cc
if MD_CPU_generic
libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE)
@@ -288,6 +299,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 \
@@ -324,7 +336,13 @@ noinst_HEADERS = \
qa_gr_fir_scc.h \
qa_gr_rotator.h \
qa_gri_mmse_fir_interpolator.h \
- qa_gri_mmse_fir_interpolator_cc.h
+ qa_gri_mmse_fir_interpolator_cc.h \
+ qa_gri_fir_filter_with_buffer_ccf.h \
+ qa_gri_fir_filter_with_buffer_ccc.h \
+ qa_gri_fir_filter_with_buffer_fcc.h \
+ qa_gri_fir_filter_with_buffer_fff.h \
+ qa_gri_fir_filter_with_buffer_fsf.h \
+ qa_gri_fir_filter_with_buffer_scc.h
if PYTHON
@@ -344,6 +362,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/Makefile.gen b/gnuradio-core/src/lib/filter/Makefile.gen
index 6809274fa..909899c05 100644
--- a/gnuradio-core/src/lib/filter/Makefile.gen
+++ b/gnuradio-core/src/lib/filter/Makefile.gen
@@ -40,7 +40,14 @@ GENERATED_H = \
gr_rational_resampler_base_fcc.h \
gr_rational_resampler_base_fff.h \
gr_rational_resampler_base_fsf.h \
- gr_rational_resampler_base_scc.h
+ gr_rational_resampler_base_scc.h \
+ gri_fir_filter_with_buffer_ccc.h \
+ gri_fir_filter_with_buffer_ccf.h \
+ gri_fir_filter_with_buffer_fcc.h \
+ gri_fir_filter_with_buffer_fff.h \
+ gri_fir_filter_with_buffer_fsf.h \
+ gri_fir_filter_with_buffer_scc.h
+
GENERATED_I = \
gr_fir_filter_ccc.i \
@@ -107,5 +114,11 @@ GENERATED_CC = \
gr_rational_resampler_base_fcc.cc \
gr_rational_resampler_base_fff.cc \
gr_rational_resampler_base_fsf.cc \
- gr_rational_resampler_base_scc.cc
+ gr_rational_resampler_base_scc.cc \
+ gri_fir_filter_with_buffer_ccc.cc \
+ gri_fir_filter_with_buffer_ccf.cc \
+ gri_fir_filter_with_buffer_fcc.cc \
+ gri_fir_filter_with_buffer_fff.cc \
+ gri_fir_filter_with_buffer_fsf.cc \
+ gri_fir_filter_with_buffer_scc.cc
diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i
index bdfb8fa8d..645607cba 100644
--- a/gnuradio-core/src/lib/filter/filter.i
+++ b/gnuradio-core/src/lib/filter/filter.i
@@ -33,6 +33,7 @@
#include <gr_goertzel_fc.h>
#include <gr_cma_equalizer_cc.h>
#include <gr_pfb_channelizer_ccf.h>
+#include <gr_pfb_synthesis_filterbank_ccf.h>
#include <gr_pfb_decimator_ccf.h>
#include <gr_pfb_interpolator_ccf.h>
#include <gr_pfb_arb_resampler_ccf.h>
@@ -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/generate_all.py b/gnuradio-core/src/lib/filter/generate_all.py
index b34e13c73..ceed2b851 100755
--- a/gnuradio-core/src/lib/filter/generate_all.py
+++ b/gnuradio-core/src/lib/filter/generate_all.py
@@ -30,6 +30,7 @@ import generate_gr_fir_sysconfig_generic
import generate_gr_fir_sysconfig
import generate_gr_fir_util
import generate_gr_fir_XXX
+import generate_gri_fir_filter_with_buffer_XXX
def generate_all():
generate_gr_fir_XXX.generate()
@@ -40,6 +41,7 @@ def generate_all():
generate_gr_fir_sysconfig_generic.generate()
generate_gr_fir_sysconfig.generate()
generate_gr_fir_util.generate()
+ generate_gri_fir_filter_with_buffer_XXX.generate()
output_glue('filter')
if __name__ == '__main__':
diff --git a/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py
new file mode 100755
index 000000000..f586b0c27
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# -*- python -*-
+#
+# 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.
+#
+
+import re
+from generate_utils import *
+
+roots = ['gri_fir_filter_with_buffer_XXX',]
+
+def code3_to_acc_code (code3):
+ if i_code (code3) == 'c' or o_code (code3) == 'c' or tap_code (code3) == 'c':
+ return 'c'
+ if i_code (code3) == 'f' or o_code (code3) == 'f' or tap_code (code3) == 'f':
+ return 'f'
+ if i_code (code3) == 'i' or o_code (code3) == 'i' or tap_code (code3) == 'i':
+ return 'i'
+ return 'i' # even short short short needs int accumulator
+
+def code3_to_input_cast (code3):
+ if i_code (code3) == 's' and o_code (code3) == 'c':
+ return '(float)'
+ return ''
+
+def expand_h_cc (root, code3):
+ d = init_dict (root, code3)
+ expand_template (d, root + '.h.t')
+ expand_template (d, root + '.cc.t')
+
+def init_dict (root, code3):
+ name = re.sub ('X+', code3, root)
+ d = standard_dict (name, code3)
+ d['INPUT_CAST'] = code3_to_input_cast (code3)
+ acc_code = code3_to_acc_code (code3)
+ d['ACC_TYPE'] = char_to_type[acc_code]
+ return d
+
+
+def generate ():
+ for r in roots:
+ for s in fir_signatures:
+ expand_h_cc (r, s)
+
+
+if __name__ == '__main__':
+ generate ()
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
index cb67b8104..db16a634b 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc
@@ -55,7 +55,6 @@ gr_pfb_channelizer_ccf::gr_pfb_channelizer_ccf (unsigned int numchans,
// This tests the specified input sample rate to see if it conforms to this
// requirement within a few significant figures.
double intp = 0;
- double x = (10000.0*rint(numchans / oversample_rate)) / 10000.0;
double fltp = modf(numchans / oversample_rate, &intp);
if(fltp != 0.0)
throw std::invalid_argument("gr_pfb_channelizer: oversample rate must be N/i for i in [1, N]");
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 000000000..9fad1bd0d
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.cc
@@ -0,0 +1,169 @@
+/* -*- 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 <gr_pfb_synthesis_filterbank_ccf.h>
+#include <gri_fft.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <cstring>
+
+gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf
+ (unsigned int numchans, const std::vector<float> &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<float> &taps)
+ : gr_sync_interpolator ("pfb_synthesis_filterbank_ccf",
+ gr_make_io_signature (1, numchans, sizeof(gr_complex)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ numchans),
+ d_updated (false), d_numchans(numchans)
+{
+ d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(d_numchans);
+
+ // Create an FIR filter for each channel and zero out the taps
+ std::vector<float> vtaps(0, d_numchans);
+ for(unsigned int i = 0; i < d_numchans; i++) {
+ d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps);
+ }
+
+ // 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<float> &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<float> 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<float>(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];
+ int numsigs = input_items.size();
+ int ndiff = d_numchans - numsigs;
+ unsigned int nhalf = (unsigned int)ceil((float)numsigs/2.0f);
+
+ 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++) {
+ // fill up the populated channels based on the
+ // number of real input streams
+ for(i = 0; i < nhalf; i++) {
+ in = (gr_complex*)input_items[i];
+ d_fft->get_inbuf()[i] = (in+i)[n];
+ }
+
+ // Make the ndiff channels around N/2 0
+ for(; i < nhalf+ndiff; i++) {
+ d_fft->get_inbuf()[i] = gr_complex(0,0);
+ }
+
+ // Finish off channels with data
+ for(; i < d_numchans; i++) {
+ in = (gr_complex*)input_items[i-ndiff];
+ d_fft->get_inbuf()[i] = (in+i)[n];
+ }
+
+ // spin through IFFT
+ d_fft->execute();
+
+ for(i = 0; i < d_numchans; i++) {
+ out[d_numchans-i-1] = d_filters[d_numchans-i-1]->filter(d_fft->get_outbuf()[i]);
+ }
+
+ out += d_numchans;
+ }
+
+ 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 000000000..f5b1cbb94
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesis_filterbank_ccf.h
@@ -0,0 +1,98 @@
+/* -*- 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 <gr_sync_interpolator.h>
+#include <gri_fir_filter_with_buffer_ccf.h>
+
+class gr_pfb_synthesis_filterbank_ccf;
+typedef boost::shared_ptr<gr_pfb_synthesis_filterbank_ccf> gr_pfb_synthesis_filterbank_ccf_sptr;
+gr_pfb_synthesis_filterbank_ccf_sptr gr_make_pfb_synthesis_filterbank_ccf
+ (unsigned int numchans, const std::vector<float> &taps);
+
+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 <EM>M</EM>
+ * \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<float> &taps);
+
+ bool d_updated;
+ unsigned int d_numchans;
+ unsigned int d_taps_per_filter;
+ gri_fft_complex *d_fft;
+ std::vector< gri_fir_filter_with_buffer_ccf*> d_filters;
+ std::vector< std::vector<float> > d_taps;
+
+
+ /*!
+ * Build the polyphase synthesis filterbank.
+ * \param numchans (unsigned integer) Specifies the number of
+ channels <EM>M</EM>
+ * \param taps (vector/list of floats) The prototype filter
+ to populate the filterbank.
+ */
+ gr_pfb_synthesis_filterbank_ccf (unsigned int numchans,
+ const std::vector<float> &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<float> &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 000000000..02a9f0255
--- /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<float> &taps);
+
+class gr_pfb_synthesis_filterbank_ccf : public gr_sync_interpolator
+{
+ private:
+ gr_pfb_synthesis_filterbank_ccf (unsigned int numchans,
+ const std::vector<float> &taps);
+
+ public:
+ ~gr_pfb_synthesis_filterbank_ccf ();
+
+ void set_taps (const std::vector<float> &taps);
+};
diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t
new file mode 100644
index 000000000..154068840
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t
@@ -0,0 +1,121 @@
+/* -*- 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 <@NAME@.h>
+
+@NAME@::@NAME@(const std::vector<@TAP_TYPE@> &taps)
+{
+ d_buffer = NULL;
+ set_taps(taps);
+}
+
+@NAME@::~@NAME@()
+{
+ if(d_buffer != NULL)
+ free(d_buffer);
+}
+
+void
+@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps)
+{
+ d_taps = gr_reverse(taps);
+
+ if(d_buffer != NULL) {
+ free(d_buffer);
+ d_buffer = NULL;
+ }
+
+ // FIXME: memalign this to 16-byte boundaries for SIMD later
+ size_t t = sizeof(@I_TYPE@) * 2 * d_taps.size();
+ d_buffer = (@I_TYPE@*)malloc(t);
+ memset(d_buffer, 0x00, t);
+ d_idx = 0;
+}
+
+@O_TYPE@
+@NAME@::filter (@I_TYPE@ input)
+{
+ unsigned int i;
+
+ d_buffer[d_idx] = input;
+ d_buffer[d_idx+ntaps()] = input;
+
+ // using the later for the case when ntaps=0;
+ // profiling shows this doesn't make a difference
+ //d_idx = (d_idx + 1) % ntaps();
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+
+ @ACC_TYPE@ out = 0;
+ for(i = 0; i < ntaps(); i++) {
+ out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i];
+ }
+ return (@O_TYPE@)out;
+}
+
+@O_TYPE@
+@NAME@::filter (const @I_TYPE@ input[], unsigned long dec)
+{
+ unsigned int i;
+
+ for(i = 0; i < dec; i++) {
+ d_buffer[d_idx] = input[i];
+ d_buffer[d_idx+ntaps()] = input[i];
+ d_idx++;
+ if(d_idx >= ntaps())
+ d_idx = 0;
+ }
+
+ @ACC_TYPE@ out = 0;
+ for(i = 0; i < ntaps(); i++) {
+ out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i];
+ }
+ return (@O_TYPE@)out;
+}
+
+void
+@NAME@::filterN (@O_TYPE@ output[],
+ const @I_TYPE@ input[],
+ unsigned long n)
+{
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(input[i]);
+ }
+}
+
+void
+@NAME@::filterNdec (@O_TYPE@ output[],
+ const @I_TYPE@ input[],
+ unsigned long n,
+ unsigned long decimate)
+{
+ unsigned long j = 0;
+ for(unsigned long i = 0; i < n; i++) {
+ output[i] = filter(&input[j], decimate);
+ j += decimate;
+ }
+}
diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t
new file mode 100644
index 000000000..23d64b65d
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t
@@ -0,0 +1,131 @@
+/* -*- 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.
+ */
+
+/*
+ * WARNING: This file is automatically generated by generate_gri_fir_XXX.py
+ * Any changes made to this file will be overwritten.
+ */
+
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <vector>
+#include <gr_types.h>
+#include <gr_reverse.h>
+#include <string.h>
+#include <cstdio>
+
+/*!
+ * \brief FIR with internal buffer for @I_TYPE@ input,
+ @O_TYPE@ output and @TAP_TYPE@ taps
+ * \ingroup filter
+ *
+ */
+
+class @NAME@ {
+
+protected:
+ std::vector<@TAP_TYPE@> d_taps; // reversed taps
+ @I_TYPE@ *d_buffer;
+ unsigned int d_idx;
+
+public:
+
+ // CONSTRUCTORS
+
+ /*!
+ * \brief construct new FIR with given taps.
+ *
+ * Note that taps must be in forward order, e.g., coefficient 0 is
+ * stored in new_taps[0], coefficient 1 is stored in
+ * new_taps[1], etc.
+ */
+ @NAME@ (const std::vector<@TAP_TYPE@> &taps);
+
+ ~@NAME@ ();
+
+ // MANIPULATORS
+
+ /*!
+ * \brief compute a single output value.
+ *
+ * \p input is a single input value of the filter type
+ *
+ * \returns the filtered input value.
+ */
+ @O_TYPE@ filter (@I_TYPE@ input);
+
+
+ /*!
+ * \brief compute a single output value; designed for decimating filters.
+ *
+ * \p input is a single input value of the filter type. The value of dec is the
+ * decimating value of the filter, so input[] must have dec valid values.
+ * The filter pushes dec number of items onto the circ. buffer before computing
+ * a single output.
+ *
+ * \returns the filtered input value.
+ */
+ @O_TYPE@ filter (const @I_TYPE@ input[], unsigned long dec);
+
+ /*!
+ * \brief compute an array of N output values.
+ *
+ * \p input must have (n - 1 + ntaps()) valid entries.
+ * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values.
+ */
+ void filterN (@O_TYPE@ output[], const @I_TYPE@ input[],
+ unsigned long n);
+
+ /*!
+ * \brief compute an array of N output values, decimating the input
+ *
+ * \p input must have (decimate * (n - 1) + ntaps()) valid entries.
+ * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to
+ * compute the output values.
+ */
+ void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[],
+ unsigned long n, unsigned long decimate);
+
+ /*!
+ * \brief install \p new_taps as the current taps.
+ */
+ void set_taps (const std::vector<@TAP_TYPE@> &taps);
+
+ // ACCESSORS
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned ntaps () const { return d_taps.size (); }
+
+ /*!
+ * \return current taps
+ */
+ const std::vector<@TAP_TYPE@> get_taps () const
+ {
+ return gr_reverse(d_taps);
+ }
+};
+
+#endif /* @GUARD_NAME@ */
diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h
new file mode 100644
index 000000000..bd7fa33cf
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_ccf.h
@@ -0,0 +1,131 @@
+/* -*- 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.
+ */
+
+/*
+ * WARNING: This file is automatically generated by generate_gri_fir_XXX.py
+ * Any changes made to this file will be overwritten.
+ */
+
+
+#ifndef INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H
+#define INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H
+
+#include <vector>
+#include <gr_types.h>
+#include <gr_reverse.h>
+#include <string.h>
+#include <cstdio>
+
+/*!
+ * \brief FIR with internal buffer for gr_complex input,
+ gr_complex output and float taps
+ * \ingroup filter
+ *
+ */
+
+class gri_fir_filter_with_buffer_ccf {
+
+protected:
+ std::vector<float> d_taps; // reversed taps
+ gr_complex *d_buffer;
+ unsigned int d_idx;
+
+public:
+
+ // CONSTRUCTORS
+
+ /*!
+ * \brief construct new FIR with given taps.
+ *
+ * Note that taps must be in forward order, e.g., coefficient 0 is
+ * stored in new_taps[0], coefficient 1 is stored in
+ * new_taps[1], etc.
+ */
+ gri_fir_filter_with_buffer_ccf (const std::vector<float> &taps);
+
+ ~gri_fir_filter_with_buffer_ccf ();
+
+ // MANIPULATORS
+
+ /*!
+ * \brief compute a single output value.
+ *
+ * \p input is a single input value of the filter type
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter (gr_complex input);
+
+
+ /*!
+ * \brief compute a single output value; designed for decimating filters.
+ *
+ * \p input is a single input value of the filter type. The value of dec is the
+ * decimating value of the filter, so input[] must have dec valid values.
+ * The filter pushes dec number of items onto the circ. buffer before computing
+ * a single output.
+ *
+ * \returns the filtered input value.
+ */
+ gr_complex filter (const gr_complex input[], unsigned long dec);
+
+ /*!
+ * \brief compute an array of N output values.
+ *
+ * \p input must have (n - 1 + ntaps()) valid entries.
+ * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values.
+ */
+ void filterN (gr_complex output[], const gr_complex input[],
+ unsigned long n);
+
+ /*!
+ * \brief compute an array of N output values, decimating the input
+ *
+ * \p input must have (decimate * (n - 1) + ntaps()) valid entries.
+ * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to
+ * compute the output values.
+ */
+ void filterNdec (gr_complex output[], const gr_complex input[],
+ unsigned long n, unsigned long decimate);
+
+ /*!
+ * \brief install \p new_taps as the current taps.
+ */
+ void set_taps (const std::vector<float> &taps);
+
+ // ACCESSORS
+
+ /*!
+ * \return number of taps in filter.
+ */
+ unsigned ntaps () const { return d_taps.size (); }
+
+ /*!
+ * \return current taps
+ */
+ const std::vector<float> get_taps () const
+ {
+ return gr_reverse(d_taps);
+ }
+};
+
+#endif /* INCLUDED_GRI_FIR_FILTER_WITH_BUFFER_CCF_H */
diff --git a/gnuradio-core/src/lib/filter/qa_filter.cc b/gnuradio-core/src/lib/filter/qa_filter.cc
index 878d48023..0d03cb0ee 100644
--- a/gnuradio-core/src/lib/filter/qa_filter.cc
+++ b/gnuradio-core/src/lib/filter/qa_filter.cc
@@ -36,6 +36,12 @@
#include <qa_gri_mmse_fir_interpolator.h>
#include <qa_gri_mmse_fir_interpolator_cc.h>
#include <qa_gr_rotator.h>
+#include <qa_gri_fir_filter_with_buffer_ccf.h>
+#include <qa_gri_fir_filter_with_buffer_ccc.h>
+#include <qa_gri_fir_filter_with_buffer_fcc.h>
+#include <qa_gri_fir_filter_with_buffer_fff.h>
+#include <qa_gri_fir_filter_with_buffer_fsf.h>
+#include <qa_gri_fir_filter_with_buffer_scc.h>
CppUnit::TestSuite *
qa_filter::suite ()
@@ -51,6 +57,12 @@ qa_filter::suite ()
s->addTest (qa_gri_mmse_fir_interpolator::suite ());
s->addTest (qa_gri_mmse_fir_interpolator_cc::suite ());
s->addTest (qa_gr_rotator::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_ccf::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_ccc::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_fcc::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_fff::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_fsf::suite ());
+ s->addTest (qa_gri_fir_filter_with_buffer_scc::suite ());
return s;
}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc
new file mode 100644
index 000000000..e87d93ebf
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc
@@ -0,0 +1,160 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_ccc.h>
+#include <gri_fir_filter_with_buffer_ccc.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef gr_complex i_type;
+typedef gr_complex o_type;
+typedef gr_complex tap_type;
+typedef gr_complex acc_type;
+
+using std::vector;
+
+#define ERR_DELTA (1e-5)
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_complex (gr_complex *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++){
+ float re = rint (uniform () * 32767);
+ float im = rint (uniform () * 32767);
+ buf[i] = gr_complex (re, im);
+ }
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+
+ return sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccc::t1 ()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccc::t2 ()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccc::t3 ()
+{
+ test_decimate(5);
+}
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_complex (input, INPUT_LEN);
+ random_complex (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_ccc *f1 = new gri_fir_filter_with_buffer_ccc(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ abs (expected_output[o]) * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h
new file mode 100644
index 000000000..f9f206f66
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_ccc : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccc);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCC_H_ */
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc
new file mode 100644
index 000000000..c25853b1e
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc
@@ -0,0 +1,167 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_ccf.h>
+#include <gri_fir_filter_with_buffer_ccf.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef gr_complex i_type;
+typedef gr_complex o_type;
+typedef float tap_type;
+typedef gr_complex acc_type;
+
+using std::vector;
+
+#define ERR_DELTA (1e-5)
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_floats (float *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = (float) rint (uniform () * 32767);
+}
+
+static void
+random_complex (gr_complex *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++){
+ float re = rint (uniform () * 32767);
+ float im = rint (uniform () * 32767);
+ buf[i] = gr_complex (re, im);
+ }
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+
+ return sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccf::t1 ()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccf::t2 ()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_ccf::t3 ()
+{
+ test_decimate(5);
+}
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_ccf::test_decimate (unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_complex (input, INPUT_LEN);
+ random_floats (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_ccf *f1 = new gri_fir_filter_with_buffer_ccf(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ abs (expected_output[o]) * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h
new file mode 100644
index 000000000..924b4bc2e
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_ccf : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccf);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCF_H_ */
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc
new file mode 100644
index 000000000..19f270200
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc
@@ -0,0 +1,168 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_fcc.h>
+#include <gri_fir_filter_with_buffer_fcc.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef float i_type;
+typedef gr_complex o_type;
+typedef gr_complex tap_type;
+typedef gr_complex acc_type;
+
+using std::vector;
+
+#define ERR_DELTA (1e-5)
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_floats (float *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = (float) rint (uniform () * 32767);
+}
+
+static void
+random_complex (gr_complex *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++){
+ float re = rint (uniform () * 32767);
+ float im = rint (uniform () * 32767);
+ buf[i] = gr_complex (re, im);
+ }
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+
+ return sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_fcc::t1()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fcc::t2()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fcc::t3()
+{
+ test_decimate(5);
+}
+
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_fcc::test_decimate(unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_floats (input, INPUT_LEN);
+ random_complex (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_fcc *f1 = new gri_fir_filter_with_buffer_fcc(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ abs (expected_output[o]) * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h
new file mode 100644
index 000000000..6201800f9
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_fcc : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fcc);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FCC_H_ */
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc
new file mode 100644
index 000000000..8401e484b
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc
@@ -0,0 +1,156 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_fff.h>
+#include <gri_fir_filter_with_buffer_fff.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef float i_type;
+typedef float o_type;
+typedef float tap_type;
+typedef float acc_type;
+
+using std::vector;
+
+#define ERR_DELTA (1e-5)
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_floats (float *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = (float) rint (uniform () * 32767);
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+ return sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_fff::t1 ()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fff::t2 ()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fff::t3 ()
+{
+ test_decimate(5);
+}
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_floats (input, INPUT_LEN);
+ random_floats (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_fff *f1 = new gri_fir_filter_with_buffer_fff(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o],
+ fabsf (expected_output[o]) * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h
new file mode 100644
index 000000000..54a9cdc53
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_fff : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fff);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FFF_H_ */
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc
new file mode 100644
index 000000000..091505380
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc
@@ -0,0 +1,147 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_fsf.h>
+#include <gri_fir_filter_with_buffer_fsf.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef float i_type;
+typedef short o_type;
+typedef float tap_type;
+typedef float acc_type;
+
+using std::vector;
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_floats (float *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = (float) rint (uniform () * 128);
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += input[i] * taps[i];
+ }
+ return (o_type)sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_fsf::t1 ()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fsf::t2 ()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_fsf::t3 ()
+{
+ test_decimate(5);
+}
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_fsf::test_decimate (unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_floats (input, INPUT_LEN);
+ random_floats (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_fsf *f1 = new gri_fir_filter_with_buffer_fsf(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_EQUAL(expected_output[o], actual_output[o]);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h
new file mode 100644
index 000000000..9c901464e
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_fsf : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fsf);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FSF_H_ */
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc
new file mode 100644
index 000000000..03cd71022
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc
@@ -0,0 +1,167 @@
+/* -*- 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 <gr_types.h>
+#include <qa_gri_fir_filter_with_buffer_scc.h>
+#include <gri_fir_filter_with_buffer_scc.h>
+#include <string.h>
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestAssert.h>
+#include <random.h>
+#include <malloc16.h>
+#include <string.h>
+
+typedef short i_type;
+typedef gr_complex o_type;
+typedef gr_complex tap_type;
+typedef gr_complex acc_type;
+
+using std::vector;
+
+#define ERR_DELTA (1e-5)
+
+#define NELEM(x) (sizeof (x) / sizeof (x[0]))
+
+static float
+uniform ()
+{
+ return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1)
+}
+
+static void
+random_shorts (short *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++)
+ buf[i] = (short) rint (uniform () * 16384);
+}
+
+static void
+random_complex (gr_complex *buf, unsigned n)
+{
+ for (unsigned i = 0; i < n; i++){
+ float re = rint (uniform () * 32767);
+ float im = rint (uniform () * 32767);
+ buf[i] = gr_complex (re, im);
+ }
+}
+
+static o_type
+ref_dotprod (const i_type input[], const tap_type taps[], int ntaps)
+{
+ acc_type sum = 0;
+ for (int i = 0; i < ntaps; i++) {
+ sum += (float)input[i] * taps[i];
+ }
+
+ return sum;
+}
+
+void
+qa_gri_fir_filter_with_buffer_scc::t1 ()
+{
+ test_decimate(1);
+}
+
+void
+qa_gri_fir_filter_with_buffer_scc::t2 ()
+{
+ test_decimate(2);
+}
+
+void
+qa_gri_fir_filter_with_buffer_scc::t3 ()
+{
+ test_decimate(5);
+}
+
+//
+// Test for ntaps in [0,9], and input lengths in [0,17].
+// This ensures that we are building the shifted taps correctly,
+// and exercises all corner cases on input alignment and length.
+//
+void
+qa_gri_fir_filter_with_buffer_scc::test_decimate (unsigned int decimate)
+{
+ const int MAX_TAPS = 9;
+ const int OUTPUT_LEN = 17;
+ const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN;
+
+ // Mem aligned buffer not really necessary, but why not?
+ i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type));
+ i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type));
+ o_type expected_output[OUTPUT_LEN];
+ o_type actual_output[OUTPUT_LEN];
+ tap_type taps[MAX_TAPS];
+
+ srandom (0); // we want reproducibility
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+
+ for (int n = 0; n <= MAX_TAPS; n++){
+ for (int ol = 0; ol <= OUTPUT_LEN; ol++){
+
+ // cerr << "@@@ n:ol " << n << ":" << ol << endl;
+
+ // build random test case
+ random_shorts (input, INPUT_LEN);
+ random_complex (taps, MAX_TAPS);
+
+ // compute expected output values
+ memset(dline, 0, INPUT_LEN*sizeof(i_type));
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ // use an actual delay line for this test
+ for(int dd = 0; dd < (int)decimate; dd++) {
+ for(int oo = INPUT_LEN-1; oo > 0; oo--)
+ dline[oo] = dline[oo-1];
+ dline[0] = input[decimate*o+dd];
+ }
+ expected_output[o] = ref_dotprod (dline, taps, n);
+ }
+
+ // build filter
+ vector<tap_type> f1_taps(&taps[0], &taps[n]);
+ gri_fir_filter_with_buffer_scc *f1 = new gri_fir_filter_with_buffer_scc(f1_taps);
+
+ // zero the output, then do the filtering
+ memset (actual_output, 0, sizeof (actual_output));
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
+
+ // check results
+ //
+ // we use a sloppy error margin because on the x86 architecture,
+ // our reference implementation is using 80 bit floating point
+ // arithmetic, while the SSE version is using 32 bit float point
+ // arithmetic.
+
+ for (int o = 0; o < (int)(ol/decimate); o++){
+ CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o],
+ abs (expected_output[o]) * ERR_DELTA);
+ }
+ delete f1;
+ }
+ }
+ free16Align(input);
+}
diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h
new file mode 100644
index 000000000..970ca3749
--- /dev/null
+++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h
@@ -0,0 +1,46 @@
+/* -*- 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_
+#define _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_fir_filter_with_buffer_scc : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_scc);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void test_decimate(unsigned int decimate);
+
+ void t1 ();
+ void t2 ();
+ void t3 ();
+
+};
+
+
+#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_SCC_H_ */
diff --git a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc
index ff997e7a9..c32398e6d 100644
--- a/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc
+++ b/gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc
@@ -161,8 +161,9 @@ gr_fll_band_edge_cc::work (int noutput_items,
const gr_complex *in = (const gr_complex *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
- float *frq, *phs;
- gr_complex *err;
+ float *frq = NULL;
+ float *phs = NULL;
+ gr_complex *err = NULL;
if(output_items.size() > 2) {
frq = (float *) output_items[1];
phs = (float *) output_items[2];
diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am
index 4c52f3ab0..a3aa36a39 100644
--- a/gnuradio-core/src/lib/runtime/Makefile.am
+++ b/gnuradio-core/src/lib/runtime/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2003,2004,2007,2008,2009 Free Software Foundation, Inc.
+# Copyright 2003,2004,2007,2008,2009,2010 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,7 +21,7 @@
include $(top_srcdir)/Makefile.common
-AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(GRUEL_INCLUDES) $(WITH_INCLUDES)
+AM_CPPFLAGS = $(GRUEL_INCLUDES) $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) $(WITH_INCLUDES)
noinst_LTLIBRARIES = libruntime.la libruntime-qa.la
diff --git a/gnuradio-core/src/lib/swig/Makefile.am b/gnuradio-core/src/lib/swig/Makefile.am
index 242f27d9c..1a50b8c8e 100644
--- a/gnuradio-core/src/lib/swig/Makefile.am
+++ b/gnuradio-core/src/lib/swig/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2001,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+# Copyright 2001,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -22,7 +22,7 @@
include $(top_srcdir)/Makefile.common
if PYTHON
-AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) -I$(srcdir) \
+AM_CPPFLAGS = -I$(srcdir) $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) \
$(WITH_INCLUDES)
EXTRA_DIST = gen-swig-bug-fix