diff --git a/common/include/villas/dsp/window.hpp b/common/include/villas/dsp/window.hpp index 025876af9..a997dd896 100644 --- a/common/include/villas/dsp/window.hpp +++ b/common/include/villas/dsp/window.hpp @@ -23,57 +23,85 @@ #pragma once -#include +#include +#include namespace villas { namespace dsp { -template -class Window { +template> +class Window : protected Container { public: - typedef typename std::vector::size_type size_type; + using iterator = typename Container::iterator; + using size_type = typename Container::size_type; protected: - std::vector data; - T init; + virtual + T filter(T in, size_type i) const + { + return in; + } - size_type steps; - size_type mask; - size_type pos; + class transform_iterator : public Container::const_iterator { + protected: + const Window *window; + + using base_iterator = typename Container::const_iterator; + + public: + transform_iterator(const Window *w) : + base_iterator(w->Container::begin()), + window(w) + { } + + T operator*() + { + auto i = (*this) - window->begin(); + const auto &v = base_iterator::operator*(); + + return window->filter(v, i); + } + }; public: - Window(size_type s = 0, T i = 0) : - init(i), - steps(s) - { - size_type len = LOG2_CEIL(s); - - /* Allocate memory for circular history buffer */ - data = std::vector(len, i); - - pos = len; - mask = len - 1; - } + Window(size_type l = 0, T i = 0) : + std::deque(l, i) + { } T update(T in) { - T out = data[(pos - steps) & mask]; + Container::push_back(in); - data[pos++ & mask] = in; + auto out = (*this)[0]; + + Container::pop_front(); return out; } - size_type getLength() const + // Expose a limited number of functions from deque + + using Container::size; + using Container::end; + + transform_iterator begin() const noexcept { - return steps; + return transform_iterator(this); } - T operator[](int i) const + T operator[](size_type i) const noexcept { - return data[(pos + i) & mask]; + auto v = Container::operator[](i); + + return filter(v, i); + } + + virtual + T getCorrectionFactor() const + { + return 1.0; } }; diff --git a/common/include/villas/dsp/window_cosine.hpp b/common/include/villas/dsp/window_cosine.hpp new file mode 100644 index 000000000..6f858f0c7 --- /dev/null +++ b/common/include/villas/dsp/window_cosine.hpp @@ -0,0 +1,97 @@ +/** A sliding/moving window. + * + * @file + * @author Steffen Vogel + * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLAScommon + * + * This program 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 of the License, or + * any later version. + * + * This program 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 this program. If not, see . + *********************************************************************************/ + +#pragma once + +#include + +#include + +#include + +namespace villas { +namespace dsp { + +template +class CosineWindow : public Window { + +public: + using size_type = typename Window::size_type; + +protected: + std::vector coefficients; + + T correctionFactor; + + virtual + T filter(T in, size_type i) const + { + return in * coefficients[i]; + } + +public: + CosineWindow(size_type len, T i = 0) : + Window(len, i), + coefficients(len), + correctionFactor(0) + { + for (unsigned i = 0; i < len; i++) { + coefficients[i] = a0 + - a1 * cos(2 * M_PI * i / len) + + a2 * cos(4 * M_PI * i / len) + - a3 * cos(6 * M_PI * i / len) + + a4 * cos(8 * M_PI * i / len); + + correctionFactor += coefficients[i]; + } + + correctionFactor /= len; + } + + + virtual + T getCorrectionFactor() const + { + return correctionFactor; + } +}; + +// From: https://en.wikipedia.org/wiki/Window_function#Cosine-sum_windows + +template +using HannWindow = CosineWindow; + +template +using HammingWindow = CosineWindow; + +template +using FlattopWindow = CosineWindow; // based on MATLAB coeffs + +template +using NuttallWindow = CosineWindow; + +template +using BlackmanWindow = CosineWindow; + +} /* namespace dsp */ +} /* namespace villas */