annotate base/Window.h @ 1078:ce82bcdc95d0

Fail upfront if the file is going to be too large. We expect the caller to split up large data sets into several MatrixFiles
author Chris Cannam
date Wed, 10 Jun 2015 13:10:26 +0100
parents 7598a78cf915
children bac86d3fc6c9
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #ifndef _WINDOW_H_
Chris@0 17 #define _WINDOW_H_
Chris@0 18
Chris@0 19 #include <cmath>
Chris@0 20 #include <iostream>
Chris@350 21 #include <string>
Chris@0 22 #include <map>
Chris@402 23 #include <cstdlib>
Chris@0 24
Chris@1059 25 #include "system/System.h"
Chris@405 26
Chris@0 27 enum WindowType {
Chris@0 28 RectangularWindow,
Chris@0 29 BartlettWindow,
Chris@0 30 HammingWindow,
Chris@0 31 HanningWindow,
Chris@0 32 BlackmanWindow,
Chris@0 33 GaussianWindow,
Chris@142 34 ParzenWindow,
Chris@142 35 NuttallWindow,
Chris@142 36 BlackmanHarrisWindow
Chris@0 37 };
Chris@0 38
Chris@0 39 template <typename T>
Chris@0 40 class Window
Chris@0 41 {
Chris@0 42 public:
Chris@0 43 /**
Chris@813 44 * Construct a windower of the given type and size.
Chris@813 45 *
Chris@813 46 * Note that the cosine windows are periodic by design, rather
Chris@813 47 * than symmetrical. (A window of size N is equivalent to a
Chris@813 48 * symmetrical window of size N+1 with the final element missing.)
Chris@0 49 */
Chris@928 50 Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); }
Chris@0 51 Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); }
Chris@0 52 Window &operator=(const Window &w) {
Chris@52 53 if (&w == this) return *this;
Chris@0 54 m_type = w.m_type;
Chris@0 55 m_size = w.m_size;
Chris@0 56 encache();
Chris@0 57 return *this;
Chris@0 58 }
Chris@142 59 virtual ~Window() { delete[] m_cache; }
Chris@0 60
Chris@0 61 void cut(T *src) const { cut(src, src); }
Chris@0 62 void cut(T *src, T *dst) const {
Chris@928 63 for (int i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
Chris@0 64 }
Chris@0 65
Chris@162 66 T getArea() { return m_area; }
Chris@928 67 T getValue(int i) { return m_cache[i]; }
Chris@140 68
Chris@0 69 WindowType getType() const { return m_type; }
Chris@928 70 int getSize() const { return m_size; }
Chris@0 71
Chris@350 72 // The names used by these functions are un-translated, for use in
Chris@350 73 // e.g. XML I/O. Use Preferences::getPropertyValueLabel if you
Chris@350 74 // want translated names for use in the user interface.
Chris@350 75 static std::string getNameForType(WindowType type);
Chris@350 76 static WindowType getTypeForName(std::string name);
Chris@350 77
Chris@0 78 protected:
Chris@0 79 WindowType m_type;
Chris@928 80 int m_size;
Chris@0 81 T *m_cache;
Chris@162 82 T m_area;
Chris@0 83
Chris@0 84 void encache();
Chris@1038 85 void cosinewin(T *, double, double, double, double);
Chris@0 86 };
Chris@0 87
Chris@0 88 template <typename T>
Chris@0 89 void Window<T>::encache()
Chris@0 90 {
Chris@928 91 const int n = m_size;
Chris@0 92 T *mult = new T[n];
Chris@141 93 int i;
Chris@0 94 for (i = 0; i < n; ++i) mult[i] = 1.0;
Chris@0 95
Chris@0 96 switch (m_type) {
Chris@0 97
Chris@0 98 case RectangularWindow:
Chris@0 99 for (i = 0; i < n; ++i) {
Chris@1038 100 mult[i] *= T(0.5);
Chris@0 101 }
Chris@0 102 break;
Chris@0 103
Chris@0 104 case BartlettWindow:
Chris@0 105 for (i = 0; i < n/2; ++i) {
Chris@1038 106 mult[i] *= T(i) / T(n/2);
Chris@1038 107 mult[i + n/2] *= T(1.0) - T(i) / T(n/2);
Chris@0 108 }
Chris@0 109 break;
Chris@0 110
Chris@0 111 case HammingWindow:
Chris@142 112 cosinewin(mult, 0.54, 0.46, 0.0, 0.0);
Chris@0 113 break;
Chris@0 114
Chris@0 115 case HanningWindow:
Chris@142 116 cosinewin(mult, 0.50, 0.50, 0.0, 0.0);
Chris@0 117 break;
Chris@0 118
Chris@0 119 case BlackmanWindow:
Chris@142 120 cosinewin(mult, 0.42, 0.50, 0.08, 0.0);
Chris@0 121 break;
Chris@0 122
Chris@0 123 case GaussianWindow:
Chris@0 124 for (i = 0; i < n; ++i) {
Chris@1038 125 mult[i] *= T(pow(2, - pow((i - (n-1)/2.0) / ((n-1)/2.0 / 3), 2)));
Chris@0 126 }
Chris@0 127 break;
Chris@0 128
Chris@0 129 case ParzenWindow:
Chris@141 130 {
Chris@141 131 int N = n-1;
Chris@141 132 for (i = 0; i < N/4; ++i) {
Chris@1038 133 T m = T(2 * pow(1.0 - (T(N)/2 - T(i)) / (T(N)/2), 3));
Chris@141 134 mult[i] *= m;
Chris@141 135 mult[N-i] *= m;
Chris@141 136 }
Chris@141 137 for (i = N/4; i <= N/2; ++i) {
Chris@141 138 int wn = i - N/2;
Chris@1038 139 T m = T(1.0 - 6 * pow(T(wn) / (T(N)/2), 2) * (1.0 - T(abs(wn)) / (T(N)/2)));
Chris@141 140 mult[i] *= m;
Chris@141 141 mult[N-i] *= m;
Chris@141 142 }
Chris@142 143 break;
Chris@142 144 }
Chris@142 145
Chris@142 146 case NuttallWindow:
Chris@142 147 cosinewin(mult, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
Chris@0 148 break;
Chris@142 149
Chris@142 150 case BlackmanHarrisWindow:
Chris@142 151 cosinewin(mult, 0.35875, 0.48829, 0.14128, 0.01168);
Chris@142 152 break;
Chris@0 153 }
Chris@0 154
Chris@0 155 m_cache = mult;
Chris@162 156
Chris@162 157 m_area = 0;
Chris@162 158 for (int i = 0; i < n; ++i) {
Chris@162 159 m_area += m_cache[i];
Chris@162 160 }
Chris@1038 161 m_area /= T(n);
Chris@0 162 }
Chris@0 163
Chris@142 164 template <typename T>
Chris@1038 165 void Window<T>::cosinewin(T *mult, double a0, double a1, double a2, double a3)
Chris@142 166 {
Chris@928 167 const int n = m_size;
Chris@142 168 for (int i = 0; i < n; ++i) {
Chris@1038 169 mult[i] *= T(a0
Chris@1038 170 - a1 * cos((2 * M_PI * i) / n)
Chris@1038 171 + a2 * cos((4 * M_PI * i) / n)
Chris@1038 172 - a3 * cos((6 * M_PI * i) / n));
Chris@142 173 }
Chris@142 174 }
Chris@142 175
Chris@350 176 template <typename T>
Chris@350 177 std::string
Chris@350 178 Window<T>::getNameForType(WindowType type)
Chris@350 179 {
Chris@350 180 switch (type) {
Chris@350 181 case RectangularWindow: return "rectangular";
Chris@350 182 case BartlettWindow: return "bartlett";
Chris@350 183 case HammingWindow: return "hamming";
Chris@350 184 case HanningWindow: return "hanning";
Chris@350 185 case BlackmanWindow: return "blackman";
Chris@350 186 case GaussianWindow: return "gaussian";
Chris@350 187 case ParzenWindow: return "parzen";
Chris@350 188 case NuttallWindow: return "nuttall";
Chris@350 189 case BlackmanHarrisWindow: return "blackman-harris";
Chris@350 190 }
Chris@350 191
Chris@350 192 std::cerr << "WARNING: Window::getNameForType: unknown type "
Chris@350 193 << type << std::endl;
Chris@350 194
Chris@350 195 return "unknown";
Chris@350 196 }
Chris@350 197
Chris@350 198 template <typename T>
Chris@350 199 WindowType
Chris@350 200 Window<T>::getTypeForName(std::string name)
Chris@350 201 {
Chris@350 202 if (name == "rectangular") return RectangularWindow;
Chris@350 203 if (name == "bartlett") return BartlettWindow;
Chris@350 204 if (name == "hamming") return HammingWindow;
Chris@350 205 if (name == "hanning") return HanningWindow;
Chris@350 206 if (name == "blackman") return BlackmanWindow;
Chris@350 207 if (name == "gaussian") return GaussianWindow;
Chris@350 208 if (name == "parzen") return ParzenWindow;
Chris@350 209 if (name == "nuttall") return NuttallWindow;
Chris@350 210 if (name == "blackman-harris") return BlackmanHarrisWindow;
Chris@350 211
Chris@350 212 std::cerr << "WARNING: Window::getTypeForName: unknown name \""
Chris@350 213 << name << "\", defaulting to \"hanning\"" << std::endl;
Chris@350 214
Chris@350 215 return HanningWindow;
Chris@350 216 }
Chris@350 217
Chris@0 218 #endif