annotate base/Window.h @ 1541:71207822a7e0 zoom

Provide fromMicroseconds (and test it)
author Chris Cannam
date Thu, 27 Sep 2018 15:53:34 +0100
parents 48e9f538e6e9
children ad5f892c0c4d
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@1270 25 #include <bqvec/VectorOps.h>
Chris@1270 26 #include <bqvec/Allocators.h>
Chris@1270 27
Chris@1059 28 #include "system/System.h"
Chris@405 29
Chris@0 30 enum WindowType {
Chris@0 31 RectangularWindow,
Chris@0 32 BartlettWindow,
Chris@0 33 HammingWindow,
Chris@0 34 HanningWindow,
Chris@0 35 BlackmanWindow,
Chris@0 36 GaussianWindow,
Chris@142 37 ParzenWindow,
Chris@142 38 NuttallWindow,
Chris@142 39 BlackmanHarrisWindow
Chris@0 40 };
Chris@0 41
Chris@0 42 template <typename T>
Chris@0 43 class Window
Chris@0 44 {
Chris@0 45 public:
Chris@0 46 /**
Chris@813 47 * Construct a windower of the given type and size.
Chris@813 48 *
Chris@813 49 * Note that the cosine windows are periodic by design, rather
Chris@813 50 * than symmetrical. (A window of size N is equivalent to a
Chris@813 51 * symmetrical window of size N+1 with the final element missing.)
Chris@0 52 */
Chris@1270 53 Window(WindowType type, int size) : m_type(type), m_size(size), m_cache(0) {
Chris@1270 54 encache();
Chris@1270 55 }
Chris@1270 56 Window(const Window &w) : m_type(w.m_type), m_size(w.m_size), m_cache(0) {
Chris@1270 57 encache();
Chris@1270 58 }
Chris@0 59 Window &operator=(const Window &w) {
Chris@1429 60 if (&w == this) return *this;
Chris@1429 61 m_type = w.m_type;
Chris@1429 62 m_size = w.m_size;
Chris@1429 63 encache();
Chris@1429 64 return *this;
Chris@0 65 }
Chris@1270 66 virtual ~Window() {
Chris@1270 67 breakfastquay::deallocate(m_cache);
Chris@1270 68 }
Chris@0 69
Chris@1270 70 inline void cut(T *const BQ_R__ block) const {
Chris@1270 71 breakfastquay::v_multiply(block, m_cache, m_size);
Chris@1270 72 }
Chris@1270 73
Chris@1270 74 inline void cut(const T *const BQ_R__ src, T *const BQ_R__ dst) const {
Chris@1270 75 breakfastquay::v_multiply(dst, src, m_cache, m_size);
Chris@0 76 }
Chris@0 77
Chris@162 78 T getArea() { return m_area; }
Chris@928 79 T getValue(int i) { return m_cache[i]; }
Chris@140 80
Chris@0 81 WindowType getType() const { return m_type; }
Chris@928 82 int getSize() const { return m_size; }
Chris@0 83
Chris@350 84 // The names used by these functions are un-translated, for use in
Chris@350 85 // e.g. XML I/O. Use Preferences::getPropertyValueLabel if you
Chris@350 86 // want translated names for use in the user interface.
Chris@350 87 static std::string getNameForType(WindowType type);
Chris@350 88 static WindowType getTypeForName(std::string name);
Chris@350 89
Chris@0 90 protected:
Chris@0 91 WindowType m_type;
Chris@928 92 int m_size;
Chris@1270 93 T *BQ_R__ m_cache;
Chris@162 94 T m_area;
Chris@0 95
Chris@0 96 void encache();
Chris@1038 97 void cosinewin(T *, double, double, double, double);
Chris@0 98 };
Chris@0 99
Chris@0 100 template <typename T>
Chris@0 101 void Window<T>::encache()
Chris@0 102 {
Chris@1270 103 if (!m_cache) m_cache = breakfastquay::allocate<T>(m_size);
Chris@1270 104
Chris@928 105 const int n = m_size;
Chris@1270 106 breakfastquay::v_set(m_cache, T(1.0), n);
Chris@141 107 int i;
Chris@0 108
Chris@0 109 switch (m_type) {
Chris@1429 110
Chris@0 111 case RectangularWindow:
Chris@1429 112 for (i = 0; i < n; ++i) {
Chris@1429 113 m_cache[i] *= T(0.5);
Chris@1429 114 }
Chris@1429 115 break;
Chris@1429 116
Chris@0 117 case BartlettWindow:
Chris@1429 118 for (i = 0; i < n/2; ++i) {
Chris@1429 119 m_cache[i] *= T(i) / T(n/2);
Chris@1429 120 m_cache[i + n/2] *= T(1.0) - T(i) / T(n/2);
Chris@1429 121 }
Chris@1429 122 break;
Chris@1429 123
Chris@0 124 case HammingWindow:
Chris@1270 125 cosinewin(m_cache, 0.54, 0.46, 0.0, 0.0);
Chris@1429 126 break;
Chris@1429 127
Chris@0 128 case HanningWindow:
Chris@1270 129 cosinewin(m_cache, 0.50, 0.50, 0.0, 0.0);
Chris@1429 130 break;
Chris@1429 131
Chris@0 132 case BlackmanWindow:
Chris@1270 133 cosinewin(m_cache, 0.42, 0.50, 0.08, 0.0);
Chris@1429 134 break;
Chris@1429 135
Chris@0 136 case GaussianWindow:
Chris@1429 137 for (i = 0; i < n; ++i) {
Chris@1270 138 m_cache[i] *= T(pow(2, - pow((i - (n-1)/2.0) / ((n-1)/2.0 / 3), 2)));
Chris@1429 139 }
Chris@1429 140 break;
Chris@1429 141
Chris@0 142 case ParzenWindow:
Chris@141 143 {
Chris@141 144 int N = n-1;
Chris@141 145 for (i = 0; i < N/4; ++i) {
Chris@1038 146 T m = T(2 * pow(1.0 - (T(N)/2 - T(i)) / (T(N)/2), 3));
Chris@1270 147 m_cache[i] *= m;
Chris@1270 148 m_cache[N-i] *= m;
Chris@141 149 }
Chris@141 150 for (i = N/4; i <= N/2; ++i) {
Chris@141 151 int wn = i - N/2;
Chris@1038 152 T m = T(1.0 - 6 * pow(T(wn) / (T(N)/2), 2) * (1.0 - T(abs(wn)) / (T(N)/2)));
Chris@1270 153 m_cache[i] *= m;
Chris@1270 154 m_cache[N-i] *= m;
Chris@141 155 }
Chris@142 156 break;
Chris@142 157 }
Chris@142 158
Chris@142 159 case NuttallWindow:
Chris@1270 160 cosinewin(m_cache, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
Chris@1429 161 break;
Chris@142 162
Chris@142 163 case BlackmanHarrisWindow:
Chris@1270 164 cosinewin(m_cache, 0.35875, 0.48829, 0.14128, 0.01168);
Chris@142 165 break;
Chris@0 166 }
Chris@1429 167
Chris@162 168 m_area = 0;
Chris@162 169 for (int i = 0; i < n; ++i) {
Chris@162 170 m_area += m_cache[i];
Chris@162 171 }
Chris@1038 172 m_area /= T(n);
Chris@0 173 }
Chris@0 174
Chris@142 175 template <typename T>
Chris@1038 176 void Window<T>::cosinewin(T *mult, double a0, double a1, double a2, double a3)
Chris@142 177 {
Chris@928 178 const int n = m_size;
Chris@142 179 for (int i = 0; i < n; ++i) {
Chris@1038 180 mult[i] *= T(a0
Chris@1038 181 - a1 * cos((2 * M_PI * i) / n)
Chris@1038 182 + a2 * cos((4 * M_PI * i) / n)
Chris@1038 183 - a3 * cos((6 * M_PI * i) / n));
Chris@142 184 }
Chris@142 185 }
Chris@142 186
Chris@350 187 template <typename T>
Chris@350 188 std::string
Chris@350 189 Window<T>::getNameForType(WindowType type)
Chris@350 190 {
Chris@350 191 switch (type) {
Chris@350 192 case RectangularWindow: return "rectangular";
Chris@350 193 case BartlettWindow: return "bartlett";
Chris@350 194 case HammingWindow: return "hamming";
Chris@350 195 case HanningWindow: return "hanning";
Chris@350 196 case BlackmanWindow: return "blackman";
Chris@350 197 case GaussianWindow: return "gaussian";
Chris@350 198 case ParzenWindow: return "parzen";
Chris@350 199 case NuttallWindow: return "nuttall";
Chris@350 200 case BlackmanHarrisWindow: return "blackman-harris";
Chris@350 201 }
Chris@350 202
Chris@350 203 std::cerr << "WARNING: Window::getNameForType: unknown type "
Chris@350 204 << type << std::endl;
Chris@350 205
Chris@350 206 return "unknown";
Chris@350 207 }
Chris@350 208
Chris@350 209 template <typename T>
Chris@350 210 WindowType
Chris@350 211 Window<T>::getTypeForName(std::string name)
Chris@350 212 {
Chris@350 213 if (name == "rectangular") return RectangularWindow;
Chris@350 214 if (name == "bartlett") return BartlettWindow;
Chris@350 215 if (name == "hamming") return HammingWindow;
Chris@350 216 if (name == "hanning") return HanningWindow;
Chris@350 217 if (name == "blackman") return BlackmanWindow;
Chris@350 218 if (name == "gaussian") return GaussianWindow;
Chris@350 219 if (name == "parzen") return ParzenWindow;
Chris@350 220 if (name == "nuttall") return NuttallWindow;
Chris@350 221 if (name == "blackman-harris") return BlackmanHarrisWindow;
Chris@350 222
Chris@350 223 std::cerr << "WARNING: Window::getTypeForName: unknown name \""
Chris@350 224 << name << "\", defaulting to \"hanning\"" << std::endl;
Chris@350 225
Chris@350 226 return HanningWindow;
Chris@350 227 }
Chris@350 228
Chris@0 229 #endif