Chris@366: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@366: /* Chris@366: Constant-Q library Chris@366: Copyright (c) 2013-2014 Queen Mary, University of London Chris@366: Chris@366: Permission is hereby granted, free of charge, to any person Chris@366: obtaining a copy of this software and associated documentation Chris@366: files (the "Software"), to deal in the Software without Chris@366: restriction, including without limitation the rights to use, copy, Chris@366: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@366: of the Software, and to permit persons to whom the Software is Chris@366: furnished to do so, subject to the following conditions: Chris@366: Chris@366: The above copyright notice and this permission notice shall be Chris@366: included in all copies or substantial portions of the Software. Chris@366: Chris@366: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@366: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@366: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@366: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY Chris@366: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@366: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@366: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@366: Chris@366: Except as contained in this notice, the names of the Centre for Chris@366: Digital Music; Queen Mary, University of London; and Chris Cannam Chris@366: shall not be used in advertising or otherwise to promote the sale, Chris@366: use or other dealings in this Software without prior written Chris@366: authorization. Chris@366: */ Chris@366: Chris@366: #ifndef WINDOW_H Chris@366: #define WINDOW_H Chris@366: Chris@366: #include Chris@366: #include Chris@366: #include Chris@366: #include Chris@366: Chris@366: #include "pi.h" Chris@366: Chris@366: enum WindowType { Chris@366: RectangularWindow, Chris@366: BartlettWindow, Chris@366: HammingWindow, Chris@366: HanningWindow, Chris@366: BlackmanWindow, Chris@366: BlackmanHarrisWindow, Chris@366: Chris@366: FirstWindow = RectangularWindow, Chris@366: LastWindow = BlackmanHarrisWindow Chris@366: }; Chris@366: Chris@366: /** Chris@366: * Various shaped windows for sample frame conditioning, including Chris@366: * cosine windows (Hann etc) and triangular and rectangular windows. Chris@366: */ Chris@366: template Chris@366: class Window Chris@366: { Chris@366: public: Chris@366: /** Chris@366: * Construct a windower of the given type and size. Chris@366: * Chris@366: * Note that the cosine windows are periodic by design, rather Chris@366: * than symmetrical. (A window of size N is equivalent to a Chris@366: * symmetrical window of size N+1 with the final element missing.) Chris@366: */ Chris@366: Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); } Chris@366: Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); } Chris@366: Window &operator=(const Window &w) { Chris@366: if (&w == this) return *this; Chris@366: m_type = w.m_type; Chris@366: m_size = w.m_size; Chris@366: encache(); Chris@366: return *this; Chris@366: } Chris@366: virtual ~Window() { delete[] m_cache; } Chris@366: Chris@366: void cut(T *src) const { cut(src, src); } Chris@366: void cut(const T *src, T *dst) const { Chris@366: for (int i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i]; Chris@366: } Chris@366: Chris@366: WindowType getType() const { return m_type; } Chris@366: int getSize() const { return m_size; } Chris@366: Chris@366: std::vector getWindowData() const { Chris@366: std::vector d; Chris@366: for (int i = 0; i < m_size; ++i) { Chris@366: d.push_back(m_cache[i]); Chris@366: } Chris@366: return d; Chris@366: } Chris@366: Chris@366: protected: Chris@366: WindowType m_type; Chris@366: int m_size; Chris@366: T *m_cache; Chris@366: Chris@366: void encache(); Chris@366: }; Chris@366: Chris@366: template Chris@366: void Window::encache() Chris@366: { Chris@366: int n = m_size; Chris@366: T *mult = new T[n]; Chris@366: int i; Chris@366: for (i = 0; i < n; ++i) mult[i] = 1.0; Chris@366: Chris@366: switch (m_type) { Chris@366: Chris@366: case RectangularWindow: Chris@366: for (i = 0; i < n; ++i) { Chris@366: mult[i] = mult[i] * 0.5; Chris@366: } Chris@366: break; Chris@366: Chris@366: case BartlettWindow: Chris@366: if (n == 2) { Chris@366: mult[0] = mult[1] = 0; // "matlab compatible" Chris@366: } else if (n == 3) { Chris@366: mult[0] = 0; Chris@366: mult[1] = mult[2] = 2./3.; Chris@366: } else if (n > 3) { Chris@366: for (i = 0; i < n/2; ++i) { Chris@366: mult[i] = mult[i] * (i / T(n/2)); Chris@366: mult[i + n - n/2] = mult[i + n - n/2] * (1.0 - (i / T(n/2))); Chris@366: } Chris@366: } Chris@366: break; Chris@366: Chris@366: case HammingWindow: Chris@366: if (n > 1) { Chris@366: for (i = 0; i < n; ++i) { Chris@366: mult[i] = mult[i] * (0.54 - 0.46 * cos(2 * M_PI * i / n)); Chris@366: } Chris@366: } Chris@366: break; Chris@366: Chris@366: case HanningWindow: Chris@366: if (n > 1) { Chris@366: for (i = 0; i < n; ++i) { Chris@366: mult[i] = mult[i] * (0.50 - 0.50 * cos(2 * M_PI * i / n)); Chris@366: } Chris@366: } Chris@366: break; Chris@366: Chris@366: case BlackmanWindow: Chris@366: if (n > 1) { Chris@366: for (i = 0; i < n; ++i) { Chris@366: mult[i] = mult[i] * (0.42 - 0.50 * cos(2 * M_PI * i / n) Chris@366: + 0.08 * cos(4 * M_PI * i / n)); Chris@366: } Chris@366: } Chris@366: break; Chris@366: Chris@366: case BlackmanHarrisWindow: Chris@366: if (n > 1) { Chris@366: for (i = 0; i < n; ++i) { Chris@366: mult[i] = mult[i] * (0.35875 Chris@366: - 0.48829 * cos(2 * M_PI * i / n) Chris@366: + 0.14128 * cos(4 * M_PI * i / n) Chris@366: - 0.01168 * cos(6 * M_PI * i / n)); Chris@366: } Chris@366: } Chris@366: break; Chris@366: } Chris@366: Chris@366: m_cache = mult; Chris@366: } Chris@366: Chris@366: #endif