annotate base/Window.h @ 974:65494d0d9ded

Fix memory leak
author Chris Cannam
date Wed, 03 Sep 2014 11:22:46 +0100
parents 6a94bb528e9d
children cc27f35aa75c
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@405 25 #include <cstdlib>
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@142 85 void cosinewin(T *, T, T, T, T);
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@141 100 mult[i] *= 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@141 106 mult[i] *= (i / T(n/2));
Chris@141 107 mult[i + n/2] *= (1.0 - (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@142 125 mult[i] *= 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@141 133 T m = 2 * pow(1.0 - (T(N)/2 - 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@141 139 T m = 1.0 - 6 * pow(wn / (T(N)/2), 2) * (1.0 - 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@162 161 m_area /= n;
Chris@0 162 }
Chris@0 163
Chris@142 164 template <typename T>
Chris@142 165 void Window<T>::cosinewin(T *mult, T a0, T a1, T a2, T a3)
Chris@142 166 {
Chris@928 167 const int n = m_size;
Chris@142 168 for (int i = 0; i < n; ++i) {
Chris@142 169 mult[i] *= (a0
Chris@262 170 - a1 * cos((2 * M_PI * i) / n)
Chris@262 171 + a2 * cos((4 * M_PI * i) / n)
Chris@262 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