summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2013-11-06 10:28:38 -0800
committerJohnathan Corgan <johnathan@corganlabs.com>2013-11-06 10:28:38 -0800
commit5f724cfd76ad52288db91b535b4366c176717d29 (patch)
tree7404cfc11c1493a022d6755104e5d8c9829adea0
parentab255b39990e559d5e92ff08b1c23e4e4faa11b6 (diff)
parent10be863fab34d9d2ca8a080b623e48f4cac0df48 (diff)
Merge remote-tracking branch 'tom/windows'
-rw-r--r--gr-fft/include/gnuradio/fft/CMakeLists.txt1
-rw-r--r--gr-fft/include/gnuradio/fft/window.h270
-rw-r--r--gr-fft/lib/CMakeLists.txt1
-rw-r--r--gr-fft/lib/window.cc333
-rw-r--r--gr-fft/python/fft/CMakeLists.txt1
-rw-r--r--gr-fft/python/fft/__init__.py2
-rw-r--r--gr-fft/python/fft/window.py179
-rw-r--r--gr-fft/swig/fft_swig.i2
-rw-r--r--gr-filter/CMakeLists.txt1
-rw-r--r--gr-filter/include/gnuradio/filter/firdes.h10
-rw-r--r--gr-filter/lib/firdes.cc81
11 files changed, 617 insertions, 264 deletions
diff --git a/gr-fft/include/gnuradio/fft/CMakeLists.txt b/gr-fft/include/gnuradio/fft/CMakeLists.txt
index 1dfa220022..55705ee660 100644
--- a/gr-fft/include/gnuradio/fft/CMakeLists.txt
+++ b/gr-fft/include/gnuradio/fft/CMakeLists.txt
@@ -27,6 +27,7 @@ install(FILES
fft_vfc.h
goertzel.h
goertzel_fc.h
+ window.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft
COMPONENT "fft_devel"
)
diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h
new file mode 100644
index 0000000000..b7479f48fb
--- /dev/null
+++ b/gr-fft/include/gnuradio/fft/window.h
@@ -0,0 +1,270 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2008,2012,2013 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 <gnuradio/fft/api.h>
+#include <vector>
+#include <cmath>
+#include <gnuradio/gr_complex.h>
+
+namespace gr {
+ namespace fft {
+
+ class FFT_API window {
+ public:
+
+ enum win_type {
+ WIN_NONE = -1, //!< don't use a window
+ WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
+ WIN_HANN = 1, //!< Hann window; max attenuation 44 dB
+ WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB
+ WIN_RECTANGULAR = 3, //!< Basic rectangular window
+ WIN_KAISER = 4, //!< Kaiser window; max attenuation a function of beta, google it
+ WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window
+ WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
+ WIN_BARTLETT = 6, //!< Barlett (triangular) window
+ WIN_FLATTOP = 7, //!< flat top window; useful in FFTs
+ };
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 3-coefficient version.
+ */
+ static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2);
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 4-coefficient version.
+ */
+ static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2, float c3);
+
+ /*!
+ * \brief Helper function to build cosine-based windows. 5-coefficient version.
+ */
+ static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4);
+
+ /*!
+ * \brief Build a rectangular window.
+ *
+ * Taps are flat across the window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> rectangular(int ntaps);
+
+ /*!
+ * \brief Build a Hamming window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hamming(int ntaps);
+
+ /*!
+ * \brief Build a Hann window (sometimes known as Hanning).
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hann(int ntaps);
+
+ /*!
+ * \brief Alias to build a Hann window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> hanning(int ntaps);
+
+ /*!
+ * \brief Build an exact Blackman window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> blackman(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 1.
+ */
+ static std::vector<float> blackman2(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 2.
+ */
+ static std::vector<float> blackman3(int ntaps);
+
+ /*!
+ * \brief Build Blackman window, variation 3.
+ */
+ static std::vector<float> blackman4(int ntaps);
+
+ /*!
+ * \brief Build a Blackman-harris window with a given attenuation.
+ *
+ * <pre>
+ * f. j. harris, "On the use of windows for harmonic analysis
+ * with the discrete Fourier transforms," Proc. IEEE, Vol. 66,
+ * ppg. 51-83, Jan. 1978.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+
+ * \param atten Attenuation factor. Must be [61, 67, 74, 92].
+ * See the above paper for details.
+ */
+ static std::vector<float> blackman_harris(int ntaps, int atten=92);
+
+ /*!
+ * Alias to gr::fft::window::blakcman_harris.
+ */
+ static std::vector<float> blackmanharris(int ntaps, int atten=92);
+
+ /*!
+ * \brief Build a Nuttal (or Blackman-Nuttal) window.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Blackman.E2.80.93Nuttall_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> nuttal(int ntaps);
+
+ /*!
+ * \brief Alias to the Nuttal window.
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> blackman_nuttal(int ntaps);
+
+ /*!
+ * \brief Build a Nuttal continuous first derivative window.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Nuttall_window.2C_continuous_first_derivative
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> nuttal_cfd(int ntaps);
+
+ /*!
+ * \brief Build a Nuttal continuous first derivative window.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Flat_top_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> flattop(int ntaps);
+
+ /*!
+ * \brief Build a Kaiser window with a given beta.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 541-545.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ * \param beta Shaping parameter of the window. See the
+ * discussion in Oppenheim and Schafer.
+ */
+ static std::vector<float> kaiser(int ntaps, double beta);
+
+ /*!
+ * \brief Build a Barlett (triangular) window.
+ *
+ * See:
+ * <pre>
+ * A. V. Oppenheim and R. W. Schafer, "Discrete-Time
+ * Signal Processing," Upper Saddle River, N.J.: Prentice
+ * Hall, 2010, pp. 535-538.
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> bartlett(int ntaps);
+
+ static std::vector<float> welch(int ntaps);
+
+ /*!
+ * \brief Build a Parzen (or de la Valle-Poussin) window.
+ *
+ * See:
+ * <pre>
+ * A. D. Poularikas, "Handbook of Formulas and Tables for
+ * Signal Processing," Springer, Oct 28, 1998
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> parzen(int ntaps);
+
+ /*!
+ * \brief Build an exponential window with a given decay.
+ *
+ * See: http://en.wikipedia.org/wiki/Window_function#Exponential_or_Poisson_window
+ *
+ * \param ntaps Number of coefficients in the window.
+ * \param d Decay of \p d dB over half the window length.
+ */
+ static std::vector<float> exponential(int ntaps, double d);
+
+ /*!
+ * \brief Build a Riemann window.
+ *
+ * See:
+ * <pre>
+ * A. D. Poularikas, "Handbook of Formulas and Tables for
+ * Signal Processing," Springer, Oct 28, 1998
+ * </pre>
+ *
+ * \param ntaps Number of coefficients in the window.
+ */
+ static std::vector<float> riemann(int ntaps);
+
+ /*!
+ * \brief Build a window using gr::fft::win_type to index the
+ * type of window desired.
+ *
+ * \param type a gr::fft::win_type index for the type of window.
+ * \param ntaps Number of coefficients in the window.
+ * \param beta Used only for building Kaiser windows.
+ */
+ static std::vector<float> build(win_type type, int ntaps, double beta);
+ };
+
+ } /* namespace fft */
+} /* namespace gr */
diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt
index c94d588f6a..045df5b4f8 100644
--- a/gr-fft/lib/CMakeLists.txt
+++ b/gr-fft/lib/CMakeLists.txt
@@ -46,6 +46,7 @@ list(APPEND fft_sources
fft_vfc_fftw.cc
goertzel_fc_impl.cc
goertzel.cc
+ window.cc
)
if(ENABLE_GR_CTRLPORT)
diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc
new file mode 100644
index 0000000000..5a28b3239d
--- /dev/null
+++ b/gr-fft/lib/window.cc
@@ -0,0 +1,333 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2007,2008,2012,2013 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 <gnuradio/fft/window.h>
+#include <stdexcept>
+
+namespace gr {
+ namespace fft {
+
+#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
+
+ static double Izero(double x)
+ {
+ double sum, u, halfx, temp;
+ int n;
+
+ sum = u = n = 1;
+ halfx = x/2.0;
+ do {
+ temp = halfx/(double)n;
+ n += 1;
+ temp *= temp;
+ u *= temp;
+ sum += u;
+ } while (u >= IzeroEPSILON*sum);
+ return(sum);
+ }
+
+ double midn(int ntaps)
+ {
+ return ntaps/2.0;
+ }
+
+ double midm1(int ntaps)
+ {
+ return (ntaps - 1.0)/2.0;
+ }
+
+ double midp1(int ntaps)
+ {
+ return (ntaps + 1.0)/2.0;
+ }
+
+ double freq(int ntaps)
+ {
+ return 2.0*M_PI/ntaps;
+ }
+
+ double rate(int ntaps)
+ {
+ return 1.0/(ntaps >> 1);
+ }
+
+ std::vector<float>
+ window::coswindow(int ntaps, float c0, float c1, float c2)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1*cos((2*M_PI*n)/M) + c2*cos((4*M_PI*n)/M);
+ return taps;
+ }
+
+ std::vector<float>
+ window::coswindow(int ntaps, float c0, float c1, float c2, float c3)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1*cos((2*M_PI*n)/M) + c2*cos((4*M_PI*n)/M) - c3*cos((6*M_PI*n)/M);
+ return taps;
+ }
+
+ std::vector<float>
+ window::coswindow(int ntaps, float c0, float c1, float c2, float c3, float c4)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = c0 - c1*cos((2*M_PI*n)/M) + c2*cos((4*M_PI*n)/M) - c3*cos((6*M_PI*n)/M) + c4*cos((8*M_PI*n)/M);
+ return taps;
+ }
+
+ std::vector<float>
+ window::rectangular(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 1;
+ return taps;
+ }
+
+ std::vector<float>
+ window::hamming(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 0.54 - 0.46 * cos((2 * M_PI * n) / M);
+ return taps;
+ }
+
+ std::vector<float>
+ window::hann(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps; n++)
+ taps[n] = 0.5 - 0.5 * cos((2 * M_PI * n) / M);
+ return taps;
+ }
+
+ std::vector<float>
+ window::hanning(int ntaps)
+ {
+ return hann(ntaps);
+ }
+
+ std::vector<float>
+ window::blackman(int ntaps)
+ {
+ return coswindow(ntaps, 0.42, 0.5, 0.08);
+ }
+
+ std::vector<float>
+ window::blackman2(int ntaps)
+ {
+ return coswindow(ntaps, 0.34401, 0.49755, 0.15844);
+ }
+
+ std::vector<float>
+ window::blackman3(int ntaps)
+ {
+ return coswindow(ntaps, 0.21747, 0.45325, 0.28256, 0.04672);
+ }
+
+ std::vector<float>
+ window::blackman4(int ntaps)
+ {
+ return coswindow(ntaps, 0.084037, 0.29145, 0.375696, 0.20762, 0.041194);
+ }
+
+ std::vector<float>
+ window::blackman_harris(int ntaps, int atten)
+ {
+ switch(atten) {
+ case(61): return coswindow(ntaps, 0.42323, 0.49755, 0.07922);
+ case(67): return coswindow(ntaps, 0.44959, 0.49364, 0.05677);
+ case(74): return coswindow(ntaps, 0.40271, 0.49703, 0.09392, 0.00183);
+ case(92): return coswindow(ntaps, 0.35875, 0.48829, 0.14128, 0.01168);
+ default:
+ throw std::out_of_range("window::blackman_harris: unknown attenuation value (must be 61, 67, 74, or 92)");
+ }
+ }
+
+ std::vector<float>
+ window::blackmanharris(int ntaps, int atten)
+ {
+ return blackman_harris(ntaps, atten);
+ }
+
+ std::vector<float>
+ window::nuttal(int ntaps)
+ {
+ return coswindow(ntaps, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
+ }
+
+ std::vector<float>
+ window::blackman_nuttal(int ntaps)
+ {
+ return nuttal(ntaps);
+ }
+
+ std::vector<float>
+ window::nuttal_cfd(int ntaps)
+ {
+ return coswindow(ntaps, 0.355768, 0.487396, 0.144232, 0.012604);
+ }
+
+ std::vector<float>
+ window::flattop(int ntaps)
+ {
+ double scale = 4.63867;
+ return coswindow(ntaps, 1.0/scale, 1.93/scale, 1.29/scale, 0.388/scale, 0.028/scale);
+ }
+
+ std::vector<float>
+ window::kaiser(int ntaps, double beta)
+ {
+ if(beta < 0)
+ throw std::out_of_range("window::kaiser: beta must be >= 0");
+
+ std::vector<float> taps(ntaps);
+
+ double IBeta = 1.0/Izero(beta);
+ double inm1 = 1.0/((double)(ntaps-1));
+ double temp;
+
+ for(int i = 0; i <= ntaps; i++) {
+ temp = 2*i*inm1 - 1;
+ taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta;
+ }
+ return taps;
+ }
+
+ std::vector<float>
+ window::bartlett(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ float M = static_cast<float>(ntaps - 1);
+
+ for(int n = 0; n < ntaps/2; n++)
+ taps[n] = 2*n/M;
+ for(int n = ntaps/2; n < ntaps; n++)
+ taps[n] = 2 - 2*n/M;
+
+ return taps;
+ }
+
+ std::vector<float>
+ window::welch(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ double m1 = midm1(ntaps);
+ double p1 = midp1(ntaps);
+ for(int i = 0; i < midn(ntaps)+1; i++) {
+ taps[i] = 1.0 - pow((i - m1) / p1, 2);
+ taps[ntaps-i-1] = taps[i];
+ }
+ return taps;
+ }
+
+ std::vector<float>
+ window::parzen(int ntaps)
+ {
+ std::vector<float> taps(ntaps);
+ double m1 = midm1(ntaps);
+ double m = midn(ntaps);
+ int i;
+ for(i = ntaps/4; i < 3*ntaps/4; i++) {
+ taps[i] = 1.0 - 6.0*pow((i-m1)/m, 2.0) * (1.0 - fabs(i-m1)/m);
+ }
+ for(; i < ntaps; i++) {
+ taps[i] = 2.0 * pow(1.0 - fabs(i-m1)/m, 3.0);
+ taps[ntaps-i-1] = taps[i];
+ }
+ return taps;
+ }
+
+ std::vector<float>
+ window::exponential(int ntaps, double d)
+ {
+ if(d < 0)
+ throw std::out_of_range("window::exponential: d must be >= 0");
+
+ double m1 = midm1(ntaps);
+ double p = 1.0 / (8.69*ntaps/(2.0*d));
+ std::vector<float> taps(ntaps);
+ for(int i = 0; i < midn(ntaps)+1; i++) {
+ taps[i] = exp(-fabs(i - m1)*p);
+ taps[ntaps-i-1] = taps[i];
+ }
+ return taps;
+ }
+
+ std::vector<float>
+ window::riemann(int ntaps)
+ {
+ double cx;
+ double sr1 = freq(ntaps);
+ double mid = midn(ntaps);
+ std::vector<float> taps(ntaps);
+ for(int i = 0; i < mid; i++) {
+ if(i == midn(ntaps)) {
+ taps[i] = 1.0;
+ taps[ntaps-i-1] = 1.0;
+ }
+ else {
+ cx = sr1*(i - mid);
+ taps[i] = sin(cx)/cx;
+ taps[ntaps-i-1] = sin(cx)/cx;
+ }
+ }
+ return taps;
+ }
+
+ std::vector<float>
+ window::build(win_type type, int ntaps, double beta)
+ {
+ switch (type) {
+ case WIN_RECTANGULAR: return rectangular(ntaps);
+ case WIN_HAMMING: return hamming(ntaps);
+ case WIN_HANN: return hann(ntaps);
+ case WIN_BLACKMAN: return blackman(ntaps);
+ case WIN_BLACKMAN_hARRIS: return blackman_harris(ntaps);
+ case WIN_KAISER: return kaiser(ntaps, beta);
+ case WIN_BARTLETT: return bartlett(ntaps);
+ case WIN_FLATTOP: return flattop(ntaps);
+ default:
+ throw std::out_of_range("window::build: type out of range");
+ }
+ }
+
+ } /* namespace fft */
+} /* namespace gr */
diff --git a/gr-fft/python/fft/CMakeLists.txt b/gr-fft/python/fft/CMakeLists.txt
index 33d37b51b9..e0bc19124d 100644
--- a/gr-fft/python/fft/CMakeLists.txt
+++ b/gr-fft/python/fft/CMakeLists.txt
@@ -24,7 +24,6 @@ GR_PYTHON_INSTALL(
FILES
__init__.py
logpwrfft.py
- window.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft
COMPONENT "fft_python"
)
diff --git a/gr-fft/python/fft/__init__.py b/gr-fft/python/fft/__init__.py
index e0803cbf38..1864353ed1 100644
--- a/gr-fft/python/fft/__init__.py
+++ b/gr-fft/python/fft/__init__.py
@@ -30,5 +30,3 @@ except ImportError:
dirname, filename = os.path.split(os.path.abspath(__file__))
__path__.append(os.path.join(dirname, "..", "..", "swig"))
from fft_swig import *
-
-from window import *
diff --git a/gr-fft/python/fft/window.py b/gr-fft/python/fft/window.py
deleted file mode 100644
index 0065a08a61..0000000000
--- a/gr-fft/python/fft/window.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#
-# Copyright 2004,2005,2009 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.
-#
-
-'''
-Routines for designing window functions.
-'''
-
-import math
-
-def izero(x):
- izeroepsilon = 1e-21
- halfx = x/2.0
- accum = u = n = 1
- while 1:
- temp = halfx/n
- n += 1
- temp *= temp
- u *= temp
- accum += u
- if u >= IzeroEPSILON*sum:
- break
- return accum
-
-def midm1(fft_size):
- return (fft_size - 1)/2
-
-def midp1(fft_size):
- return (fft_size+1)/2
-
-def freq(fft_size):
- return 2.0*math.pi/fft_size
-
-def rate(fft_size):
- return 1.0/(fft_size >> 1)
-
-def expn(fft_size):
- math.log(2.0)/(midn(fft_size) + 1.0)
-
-def hamming(fft_size):
- window = []
- for index in xrange(fft_size):
- window.append(0.54 - 0.46 * math.cos (2 * math.pi / fft_size * index)) # Hamming window
- return window
-
-def hanning(fft_size):
- window = []
- for index in xrange(fft_size):
- window.append(0.5 - 0.5 * math.cos (2 * math.pi / fft_size * index)) # von Hann window
- return window
-
-def welch(fft_size):
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- window[j] = window[index] = (1.0 - math.sqrt((index - midm1(fft_size)) / midp1(fft_size)))
- j -= 1
- return window
-
-def parzen(fft_size):
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- window[j] = window[index] = (1.0 - math.abs((index - midm1(fft_size)) / midp1(fft_size)))
- j -= 1
- return window
-
-def bartlett(fft_size):
- mfrq = freq(fft_size)
- angle = 0
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- window[j] = window[index] = angle
- angle += freq
- j -= 1
- return window
-
-def blackman2(fft_size):
- mfrq = freq(fft_size)
- angle = 0
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- cx = math.cos(angle)
- window[j] = window[index] = (.34401 + (cx * (-.49755 + (cx * .15844))))
- angle += freq
- j -= 1
- return window
-
-def blackman3(fft_size):
- mfrq = freq(fft_size)
- angle = 0
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- cx = math.cos(angle)
- window[j] = window[index] = (.21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672))))))
- angle += freq
- j -= 1
- return window
-
-def blackman4(fft_size):
- mfrq = freq(fft_size)
- angle = 0
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- cx = math.cos(angle)
- window[j] = window[index] = (.084037 + (cx * (-.29145 + (cx * (.375696 + (cx * (-.20762 + (cx * .041194))))))))
- angle += freq
- j -= 1
- return window
-
-def exponential(fft_size):
- expsum = 1.0
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)+1):
- window[j] = window[i] = (expsum - 1.0)
- expsum *= expn(fft_size)
- j -= 1
- return window
-
-def riemann(fft_size):
- sr1 = freq(fft_size)
- window = [0 for i in range(fft_size)]
- j = fft_size-1
- for index in xrange(midn(fft_size)):
- if index == midn(fft_size):
- window[index] = window[j] = 1.0
- else:
- cx = sr1*midn(fft_size) - index
- window[index] = window[j] = math.sin(cx)/cx
- j -= 1
- return window
-
-def kaiser(fft_size,beta):
- ibeta = 1.0/izero(beta)
- inm1 = 1.0/(fft_size)
- window = [0 for i in range(fft_size)]
- for index in xrange(fft_size):
- window[index] = izero(beta*math.sqrt(1.0 - (index * inm1)*(index * inm1))) * ibeta
- return window
-
-# Closure to generate functions to create cos windows
-
-def coswindow(coeffs):
- def closure(fft_size):
- window = [0] * fft_size
- #print list(enumerate(coeffs))
- for w_index in range(fft_size):
- for (c_index, coeff) in enumerate(coeffs):
- window[w_index] += (-1)**c_index * coeff * math.cos(2.0*c_index*math.pi*(w_index+0.5)/(fft_size-1))
- return window
- return closure
-
-blackmanharris = coswindow((0.35875,0.48829,0.14128,0.01168))
-nuttall = coswindow((0.3635819,0.4891775,0.1365995,0.0106411)) # Wikipedia calls this Blackman-Nuttall
-nuttall_cfd = coswindow((0.355768,0.487396,0.144232,0.012604)) # Wikipedia calls this Nuttall, continuous first deriv
-flattop = coswindow((1.0,1.93,1.29,0.388,0.032)) # Flat top window, coeffs from Wikipedia
-rectangular = lambda fft_size: [1]*fft_size
diff --git a/gr-fft/swig/fft_swig.i b/gr-fft/swig/fft_swig.i
index edc3c594ac..062328f12a 100644
--- a/gr-fft/swig/fft_swig.i
+++ b/gr-fft/swig/fft_swig.i
@@ -31,11 +31,13 @@
#include "gnuradio/fft/fft_vcc.h"
#include "gnuradio/fft/fft_vfc.h"
#include "gnuradio/fft/goertzel_fc.h"
+#include "gnuradio/fft/window.h"
%}
%include "gnuradio/fft/fft_vcc.h"
%include "gnuradio/fft/fft_vfc.h"
%include "gnuradio/fft/goertzel_fc.h"
+%include "gnuradio/fft/window.h"
GR_SWIG_BLOCK_MAGIC2(fft, fft_vcc);
GR_SWIG_BLOCK_MAGIC2(fft, fft_vfc);
diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt
index ccc9cb7fdf..c0d46d521a 100644
--- a/gr-filter/CMakeLists.txt
+++ b/gr-filter/CMakeLists.txt
@@ -40,6 +40,7 @@ GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/lib
${CMAKE_CURRENT_BINARY_DIR}/include
+ ${GR_FFT_INCLUDE_DIRS}
)
SET(GR_PKG_FILTER_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/filter)
diff --git a/gr-filter/include/gnuradio/filter/firdes.h b/gr-filter/include/gnuradio/filter/firdes.h
index d2ab23d186..7e22cbde06 100644
--- a/gr-filter/include/gnuradio/filter/firdes.h
+++ b/gr-filter/include/gnuradio/filter/firdes.h
@@ -27,6 +27,7 @@
#include <vector>
#include <cmath>
#include <gnuradio/gr_complex.h>
+#include <gnuradio/fft/window.h>
namespace gr {
namespace filter {
@@ -38,7 +39,9 @@ namespace gr {
class FILTER_API firdes {
public:
-
+
+ // WARNING: deprecated, now located in gr::fft::window.
+ // We will be removing this in 3.8.
enum win_type {
WIN_NONE = -1, //!< don't use a window
WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
@@ -49,8 +52,10 @@ namespace gr {
WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window
WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
WIN_BARTLETT = 6, //!< Barlett (triangular) window
+ WIN_FLATTOP = 7, //!< flat top window; useful in FFTs
};
+ static std::vector<float> window(win_type type, int ntaps, double beta);
// ... class methods ...
@@ -353,9 +358,6 @@ namespace gr {
double bt, // Bandwidth to bitrate ratio
int ntaps);
- // window functions ...
- static std::vector<float> window (win_type type, int ntaps, double beta);
-
private:
static double bessi0(double x);
static void sanity_check_1f(double sampling_freq, double f1,
diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc
index dd3c124565..93dfec5bc8 100644
--- a/gr-filter/lib/firdes.cc
+++ b/gr-filter/lib/firdes.cc
@@ -31,27 +31,13 @@ using std::vector;
namespace gr {
namespace filter {
-
-#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */
- static double Izero(double x)
+ std::vector<float>
+ firdes::window(win_type type, int ntaps, double beta)
{
- double sum, u, halfx, temp;
- int n;
-
- sum = u = n = 1;
- halfx = x/2.0;
- do {
- temp = halfx/(double)n;
- n += 1;
- temp *= temp;
- u *= temp;
- sum += u;
- } while (u >= IzeroEPSILON*sum);
- return(sum);
+ return fft::window::build(static_cast<fft::window::win_type>(type), ntaps, beta);
}
-
//
// === Low Pass ===
//
@@ -736,67 +722,6 @@ namespace gr {
return ans;
}
- vector<float>
- firdes::window (win_type type, int ntaps, double beta)
- {
- vector<float> taps(ntaps);
- int M = ntaps - 1; // filter order
-
- switch (type) {
- case WIN_RECTANGULAR:
- for(int n = 0; n < ntaps; n++)
- taps[n] = 1;
- break;
-
- case WIN_HAMMING:
- for(int n = 0; n < ntaps; n++)
- taps[n] = 0.54 - 0.46 * cos((2 * M_PI * n) / M);
- break;
-
- case WIN_HANN:
- for(int n = 0; n < ntaps; n++)
- taps[n] = 0.5 - 0.5 * cos((2 * M_PI * n) / M);
- break;
-
- case WIN_BLACKMAN:
- for(int n = 0; n < ntaps; n++)
- taps[n] = 0.42 - 0.50 * cos((2*M_PI * n) / M)
- + 0.08 * cos((4*M_PI * n) / M);
- break;
-
- case WIN_BLACKMAN_hARRIS:
- for(int n = -ntaps/2; n < ntaps/2; n++)
- taps[n+ntaps/2] = 0.35875 + 0.48829*cos((2*M_PI * n) / (float)M) +
- 0.14128*cos((4*M_PI * n) / (float)M) + 0.01168*cos((6*M_PI * n) / (float)M);
- break;
-
- case WIN_KAISER:
- {
- double IBeta = 1.0/Izero(beta);
- double inm1 = 1.0/((double)(ntaps-1));
- double temp;
-
- for(int i = 0; i <= ntaps; i++) {
- temp = 2*i*inm1 - 1;
- taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta;
- }
- }
- break;
-
- case WIN_BARTLETT:
- for(int n = 0; n <= ntaps/2; n++)
- taps[n] = 2*n / (float)M;
- for(int n = ntaps/2 + 1; n < ntaps; n++)
- taps[n] = 2 - 2*n / (float)M;
- break;
-
- default:
- throw std::out_of_range("firdes:window: type out of range");
- }
-
- return taps;
- }
-
void
firdes::sanity_check_1f(double sampling_freq,
double fa, // cutoff freq