Hi, I was working on some spectral estimation code when I noticed there is no code for window functions in the C++ domain. I think this is pretty basic functionality, so I added a patch which contains some basic window functions.
I did not bother to export them to Python domain, since numpy comes with some own window functions. The qa code is pretty basic, but should do for these simple mathematical codes. I put all of it in src/lib/filter (tapering is basically time-domain filtering...). There's a couple of common windows; one I would like to have put in but didn't is the Kaiser window - if someone points me to a Bessel function implementation in C++ I might add that one, too. Here comes the patch. Cheers, Martin -- Dipl.-Ing. Martin Braun Phone: +49-(0)721-608 3790 Institut fuer Nachrichtentechnik Fax: +49-(0)721-608 6071 Universitaet Karlsruhe (TH) http://www.int.uni-karlsruhe.de/
Index: gnuradio-core/src/lib/filter/qa_gri_window_function.h
===================================================================
--- gnuradio-core/src/lib/filter/qa_gri_window_function.h (revision 0)
+++ gnuradio-core/src/lib/filter/qa_gri_window_function.h (revision 0)
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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_WINDOW_FUNCTION_H_
+#define _QA_GRI_WINDOW_FUNCTION_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_gri_window_function : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_gri_window_function);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+
+ void t1 ();
+
+};
+
+
+#endif /* _QA_GRI_WINDOW_FUNCTION_H_ */
+
Index: gnuradio-core/src/lib/filter/gri_window_function.cc
===================================================================
--- gnuradio-core/src/lib/filter/gri_window_function.cc (revision 0)
+++ gnuradio-core/src/lib/filter/gri_window_function.cc (revision 0)
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006 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 <cmath>
+#include <gri_window_function.h>
+
+const float PI = 3.14159265358979323846f;
+
+// TODO: The symmetry of the window can be used to speed this up.
+
+void
+gri_window_hamming(std::vector<float> &window)
+{
+ int N = window.size();
+ double cos_arg = 2.0 * PI / (N-1);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = 0.53836 - 0.46164 * cos(cos_arg * i);
+ }
+}
+
+
+void
+gri_window_hann(std::vector<float> &window)
+{
+ int N = window.size();
+ double cos_arg = 2.0 * PI / (N-1);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = 0.5 - 0.5 * cos(cos_arg * i);
+ }
+}
+
+
+void
+gri_window_cosine(std::vector<float> &window)
+{
+ int N = window.size();
+ double sin_arg = PI / (N-1);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = sin(sin_arg * i);
+ }
+}
+
+
+void
+gri_window_bartlett(std::vector<float> &window)
+{
+ int N = window.size();
+ double twooverNminusone = 2.0 / (N-1);
+ double Nminusoneovertwo = 1/twooverNminusone;
+
+ for (int i = 0; i < N; i++) {
+ window[i] = 1 - twooverNminusone * fabs(i - Nminusoneovertwo);
+ }
+}
+
+
+void
+gri_window_triangular(std::vector<float> &window)
+{
+ int N = window.size();
+ double twooverN = 2.0 / N;
+ double Nminusoneovertwo = 0.5 * (N-1);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = 1 - twooverN * fabs(i - Nminusoneovertwo);
+ }
+}
+
+
+void
+gri_window_gauss(std::vector<float> &window, float sigma)
+{
+ int N = window.size();
+ double Nminusoneovertwo = 0.5 * (N-1);
+
+ for (int i = 0; i < N; i++) {
+ double exponent = (i - Nminusoneovertwo) / (sigma * Nminusoneovertwo);
+ window[i] = exp(-0.5 * exponent * exponent);
+ }
+}
+
+
+void
+gri_window_bartletthann(std::vector<float> &window)
+{
+ int N = window.size();
+ double cos_arg = 2.0 * PI / (N-1);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = 0.62 - 0.48 * fabs(((float) i) / (N-1) - 0.5) - 0.38 * cos(cos_arg * i);
+ }
+}
+
+
+void
+gri_window_blackman(std::vector<float> &window, float alpha)
+{
+ int N = window.size();
+ double cos_arg = 2.0 * PI / (N-1);
+ double a0 = 0.5 * (1.0 - alpha);
+
+ for (int i = 0; i < N; i++) {
+ window[i] = a0 - 0.5 * cos(cos_arg * i) + 0.5 * alpha * cos(2 * cos_arg * i);
+ }
+}
+
+
+
+
+void
+gri_window_blackmanharris(std::vector<float> &window)
+{
+ int N = window.size();
+ double cos_arg = 2.0 * PI / N;
+ double a0 = 0.35875, a1 = 0.48829, a2 = 0.14128, a3 = 0.01168;
+
+ for (int i = 0; i < N; i++) {
+ window[i] = a0 - a1 * cos(cos_arg * i) + a2 * cos(2 * cos_arg * i) - a3 * cos(3 * cos_arg * i);
+ }
+}
+
+
+
+
+
Index: gnuradio-core/src/lib/filter/qa_gri_window_function.cc
===================================================================
--- gnuradio-core/src/lib/filter/qa_gri_window_function.cc (revision 0)
+++ gnuradio-core/src/lib/filter/qa_gri_window_function.cc (revision 0)
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 <qa_gri_window_function.h>
+#include <gri_window_function.h>
+#include <cppunit/TestAssert.h>
+#include <gr_types.h>
+#include <vector>
+
+
+using std::vector;
+
+#define ERR_DELTA (1e-4)
+
+void
+assert_window_correct(std::vector<float> &window, double *reference)
+{
+ for (unsigned i = 0; i < window.size(); i++) {
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(reference[i], window[i], ERR_DELTA);
+ }
+}
+
+
+void
+qa_gri_window_function::t1 ()
+{
+ const int n_samples = 6;
+ double hamming[n_samples] = {0.0767, 0.3957, 0.9118, 0.9118, 0.3957, 0.0767};
+ double hann[n_samples] = {0.0, 0.3455, 0.9045, 0.9045, 0.3455, 0};
+ double cosine[n_samples] = {0.0000, 0.5878, 0.9511, 0.9511, 0.5878, 0.0000};
+ double bartlett[n_samples] = {0.0000, 0.4000, 0.8000, 0.8000, 0.4000, 0.0000};
+ double triangular[n_samples] = {0.1667, 0.5000, 0.8333, 0.8333, 0.5000, 0.1667};
+ double gauss[n_samples] = {0.0439, 0.3247, 0.8825, 0.8825, 0.3247, 0.0439};
+ double bartletthann[n_samples] = {0.0000, 0.3586, 0.8794, 0.8794, 0.3586, 0.0000};
+ double blackman[n_samples] = {0.0000, 0.2008, 0.8492, 0.8492, 0.2008, 0.0000};
+ double blackmanharris[n_samples] = {0.0001, 0.0556, 0.5206, 1.0000, 0.5206, 0.0556};
+
+ std::vector<float> window(6);
+
+ gri_window_hamming(window);
+ assert_window_correct(window, hamming);
+ gri_window_hann(window);
+ assert_window_correct(window, hann);
+ gri_window_cosine(window);
+ assert_window_correct(window, cosine);
+ gri_window_bartlett(window);
+ assert_window_correct(window, bartlett);
+ gri_window_triangular(window);
+ assert_window_correct(window, triangular);
+ gri_window_gauss(window, 0.4);
+ assert_window_correct(window, gauss);
+ gri_window_bartletthann(window);
+ assert_window_correct(window, bartletthann);
+ gri_window_blackman(window);
+ assert_window_correct(window, blackman);
+ gri_window_blackmanharris(window);
+ assert_window_correct(window, blackmanharris);
+}
+
Index: gnuradio-core/src/lib/filter/Makefile.am
===================================================================
--- gnuradio-core/src/lib/filter/Makefile.am (revision 10402)
+++ gnuradio-core/src/lib/filter/Makefile.am (working copy)
@@ -218,6 +218,7 @@
gri_goertzel.cc \
gri_mmse_fir_interpolator.cc \
gri_mmse_fir_interpolator_cc.cc \
+ gri_window_function.cc \
complex_dotprod_generic.cc \
ccomplex_dotprod_generic.cc \
float_dotprod_generic.c \
@@ -232,7 +233,8 @@
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_window_function.cc
if MD_CPU_generic
libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE)
@@ -288,6 +290,7 @@
gri_iir.h \
gri_mmse_fir_interpolator.h \
gri_mmse_fir_interpolator_cc.h \
+ gri_window_function.h \
qa_filter.h \
short_dotprod_generic.h \
short_dotprod_x86.h \
@@ -321,7 +324,8 @@
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_window_function.h
Index: gnuradio-core/src/lib/filter/qa_filter.cc
===================================================================
--- gnuradio-core/src/lib/filter/qa_filter.cc (revision 10402)
+++ gnuradio-core/src/lib/filter/qa_filter.cc (working copy)
@@ -36,6 +36,7 @@
#include <qa_gri_mmse_fir_interpolator.h>
#include <qa_gri_mmse_fir_interpolator_cc.h>
#include <qa_gr_rotator.h>
+#include <qa_gri_window_function.h>
CppUnit::TestSuite *
qa_filter::suite ()
@@ -51,6 +52,7 @@
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_window_function::suite ());
return s;
}
Index: gnuradio-core/src/lib/filter/gri_window_function.h
===================================================================
--- gnuradio-core/src/lib/filter/gri_window_function.h (revision 0)
+++ gnuradio-core/src/lib/filter/gri_window_function.h (revision 0)
@@ -0,0 +1,130 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006 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.
+ */
+
+
+#include <vector>
+
+/**
+ * \brief Create an N-point symmetric Hamming window.
+ *
+ * Fills the given vector with a Hamming window.
+ *
+ * w(n) = 0.53836 - 0.46164 * cos(2 pi n / (N - 1))
+ */
+void
+gri_window_hamming(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric Hann window.
+ *
+ * Fills the given vector with a Hann window.
+ *
+ * w(n) = 0.5 - 0.5 * cos(2 pi n / (N - 1))
+ */
+void
+gri_window_hann(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric cosine window.
+ *
+ * Fills the given vector with a cosine window.
+ *
+ * w(n) = sin(pi n / (N - 1))
+ */
+void
+gri_window_cosine(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric Bartlett window.
+ *
+ * Fills the given vector with a Bartlett window.
+ *
+ * w(n) = 1 - 2/(N-1) |n - (N-1) / 2|
+ */
+void
+gri_window_bartlett(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric triangular window.
+ *
+ * Fills the given vector with a triangular window. This is similar to the
+ * Bartlett window, but without zero endpoints and thus discards less information.
+ *
+ * w(n) = 1 - 2/N |n - (N-1) / 2|
+ */
+void
+gri_window_triangular(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric Gaussian window.
+ *
+ * Fills the given vector with a Gaussian window. Note the parameter sigma is the standard
+ * deviation of the Gauss function, and not, as in some other software, its inverse.
+ *
+ * w(n) = exp(-1/2 ((n - (N-1)/2) / (sigma * ((N-1)/2))))
+ */
+void
+gri_window_gauss(std::vector<float> &window, float sigma);
+
+
+/**
+ * \brief Create an N-point symmetric Bartlett-Hann window.
+ *
+ * Fills the given vector with a Bartlett-Hann window.
+ *
+ * w(n) = 0.62 - 0.48 |n/N-1 - 1/2| - 0.38 cos(2pi n / N-1)
+ */
+void
+gri_window_bartletthann(std::vector<float> &window);
+
+
+/**
+ * \brief Create an N-point symmetric Blackman window.
+ *
+ * Fills the given vector with a Blackman window.
+ *
+ * w(n) = a0 - 1/2 cos(2 pi n / N-1) + a2 cos(4 pi n / N-1)
+ *
+ * where a0 = 1-alpha / 2 and a1 = alpha/2
+ *
+ * Unless given otherwise, alpha is the usual value of 0.16.
+ */
+void
+gri_window_blackman(std::vector<float> &window, float alpha = 0.16);
+
+
+/**
+ * \brief Create an N-point Blackman-Harris window.
+ *
+ * Fills the given vector with a Blackman-Harris window.
+ *
+ * w(n) = a0 - a1 cos(2 pi n / N) + a2 cos(4 pi n / N) - a3 cos(6 pi n / N)
+ *
+ * where a0 = 0.35875, a1 = 0.48829, a2 = 0.14128, a3 = 0.01168.
+ */
+void
+gri_window_blackmanharris(std::vector<float> &window);
pgpz4ZHm1czUq.pgp
Description: PGP signature
_______________________________________________ Patch-gnuradio mailing list [email protected] http://lists.gnu.org/mailman/listinfo/patch-gnuradio
