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