// 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]");
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[],
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;
+ }
+}
/*!
* \brief compute a single output value.
*
- * \p input must have ntaps() valid entries.
- * input[0] .. input[ntaps() - 1] are referenced to compute the 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.
*
* compute the output values.
*/
void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[],
- unsigned long n, unsigned decimate);
+ unsigned long n, unsigned long decimate);
/*!
* \brief install \p new_taps as the current taps.
+++ /dev/null
-/* -*- 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 must have ntaps() valid entries.
- * input[0] .. input[ntaps() - 1] are referenced to compute the output value.
- *
- * \returns the filtered input value.
- */
- gr_complex filter (gr_complex input);
-
- /*!
- * \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 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 */
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::t1 ()
+qa_gri_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
//
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
- for (int o = 0; o < ol; o++){
+ 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);
}
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 ();
+ void t2 ();
+ void t3 ();
};
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::t1 ()
+qa_gri_fir_filter_with_buffer_ccf::test_decimate (unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
//
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
- for (int o = 0; o < ol; o++){
+ 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);
}
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 ();
+ void t2 ();
+ void t3 ();
};
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::t1 ()
+qa_gri_fir_filter_with_buffer_fcc::test_decimate(unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
//
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
- for (int o = 0; o < ol; o++){
+ 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);
}
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 ();
+ void t2 ();
+ void t3 ();
};
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::t1 ()
+qa_gri_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
//
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
- for (int o = 0; o < ol; o++){
+ 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);
}
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 ();
+ void t2 ();
+ void t3 ();
};
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::t1 ()
+qa_gri_fir_filter_with_buffer_fsf::test_decimate (unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
CPPUNIT_ASSERT_EQUAL(expected_output[o], actual_output[o]);
}
delete f1;
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 ();
+ void t2 ();
+ void t3 ();
};
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::t1 ()
+qa_gri_fir_filter_with_buffer_scc::test_decimate (unsigned int decimate)
{
const int MAX_TAPS = 9;
const int OUTPUT_LEN = 17;
// compute expected output values
memset(dline, 0, INPUT_LEN*sizeof(i_type));
- for (int o = 0; o < ol; o++){
+ for (int o = 0; o < (int)(ol/decimate); o++){
// use an actual delay line for this test
- for(int oo = INPUT_LEN-1; oo > 0; oo--)
- dline[oo] = dline[oo-1];
- dline[0] = input[o];
+ 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);
}
// zero the output, then do the filtering
memset (actual_output, 0, sizeof (actual_output));
- f1->filterN (actual_output, input, ol);
+ f1->filterNdec (actual_output, input, ol/decimate, decimate);
// check results
//
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
- for (int o = 0; o < ol; o++){
+ 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);
}
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 ();
+ void t2 ();
+ void t3 ();
};
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];