summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-fft/include/gnuradio/fft/window.h4
-rw-r--r--gr-fft/lib/window.cc23
-rw-r--r--gr-fft/python/fft/bindings/window_python.cc5
-rw-r--r--gr-fft/python/fft/qa_window.py37
4 files changed, 65 insertions, 4 deletions
diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h
index 0ab333e175..6739f9a0bd 100644
--- a/gr-fft/include/gnuradio/fft/window.h
+++ b/gr-fft/include/gnuradio/fft/window.h
@@ -331,8 +331,10 @@ public:
* \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.
+ * \param normalize If true, return a window with unit power
*/
- static std::vector<float> build(win_type type, int ntaps, double beta = 6.76);
+ static std::vector<float>
+ build(win_type type, int ntaps, double beta = 6.76, const bool normalize = false);
};
} /* namespace fft */
diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc
index 430b435bd4..faebdd4f56 100644
--- a/gr-fft/lib/window.cc
+++ b/gr-fft/lib/window.cc
@@ -14,6 +14,8 @@
#include <gnuradio/fft/window.h>
#include <gnuradio/math.h>
+#include <algorithm>
+#include <numeric>
#include <stdexcept>
namespace gr {
@@ -355,8 +357,27 @@ std::vector<float> window::gaussian(int ntaps, float sigma)
return taps;
}
-std::vector<float> window::build(win_type type, int ntaps, double beta)
+std::vector<float>
+window::build(win_type type, int ntaps, double beta, const bool normalize)
{
+ // If we want a normalized window, we get a non-normalized one first, then
+ // normalize it here:
+ if (normalize) {
+ auto win = build(type, ntaps, beta, false);
+ const double pwr_acc = // sum(win**2) / len(win)
+ std::accumulate(win.cbegin(),
+ win.cend(),
+ 0.0,
+ [](const double a, const double b) { return a + b * b; }) /
+ win.size();
+ const float norm_fac = static_cast<float>(std::sqrt(pwr_acc));
+ std::transform(win.begin(), win.end(), win.begin(), [norm_fac](const float tap) {
+ return tap / norm_fac;
+ });
+ return win;
+ }
+
+ // Create non-normalized window:
switch (type) {
case WIN_RECTANGULAR:
return rectangular(ntaps);
diff --git a/gr-fft/python/fft/bindings/window_python.cc b/gr-fft/python/fft/bindings/window_python.cc
index 51dd7200d1..e04a6c59df 100644
--- a/gr-fft/python/fft/bindings/window_python.cc
+++ b/gr-fft/python/fft/bindings/window_python.cc
@@ -13,8 +13,8 @@
/* If manual edits are made, the following tags should be modified accordingly. */
/* BINDTOOL_GEN_AUTOMATIC(0) */
/* BINDTOOL_USE_PYGCCXML(0) */
-/* BINDTOOL_HEADER_FILE(window.h) */
-/* BINDTOOL_HEADER_FILE_HASH(b55c3b96105267729782fc5262efa28a) */
+/* BINDTOOL_HEADER_FILE(window.h) */
+/* BINDTOOL_HEADER_FILE_HASH(22de6d8875628eec777952b4902a09e9) */
/***********************************************************************************/
#include <pybind11/complex.h>
@@ -176,6 +176,7 @@ void bind_window(py::module& m)
py::arg("type"),
py::arg("ntaps"),
py::arg("beta") = 6.76,
+ py::arg("normalize") = false,
D(window, build))
;
diff --git a/gr-fft/python/fft/qa_window.py b/gr-fft/python/fft/qa_window.py
new file mode 100644
index 0000000000..f5afd2640d
--- /dev/null
+++ b/gr-fft/python/fft/qa_window.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Unit tests for fft.window
+"""
+
+import numpy
+from gnuradio import gr_unittest
+from gnuradio import fft
+
+class test_window(gr_unittest.TestCase):
+ """
+ Unit tests for fft.window
+ """
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_normwin(self):
+ """
+ Verify window normalization
+ """
+ win = fft.window.build(fft.win_type.WIN_BLACKMAN_hARRIS, 21, normalize=True)
+ power = numpy.sum([x*x for x in win])/len(win)
+ self.assertAlmostEqual(power, 1.0)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_window)