summaryrefslogtreecommitdiff
path: root/gr-fft/lib
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2013-11-05 13:52:40 -0500
committerTom Rondeau <tom@trondeau.com>2013-11-05 14:12:38 -0500
commit10be863fab34d9d2ca8a080b623e48f4cac0df48 (patch)
tree514dc7e3197f7a56fd8fa734685f70afefc83949 /gr-fft/lib
parent466c218e78b8a566bb8e6eb5ed33f95a3409eb29 (diff)
fft: Moved all window building functions into C++.
Remove window.py. All windows built using C++ functions. Exported into Python in same module (from gnuradio.fft import window). Removed all window building work in firdes, too. firdes.window now makes a direct call to fft.window.build with same parameters. Added documentation for window functions, including references to where to find coefficients and equations for (most of) the windows. All changes should not affect existing code. f
Diffstat (limited to 'gr-fft/lib')
-rw-r--r--gr-fft/lib/CMakeLists.txt1
-rw-r--r--gr-fft/lib/window.cc333
2 files changed, 334 insertions, 0 deletions
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 */