svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #ifndef _WINDOW_H_ 00017 #define _WINDOW_H_ 00018 00019 #include <cmath> 00020 #include <iostream> 00021 #include <string> 00022 #include <map> 00023 #include <cstdlib> 00024 00025 #include <cstdlib> 00026 00027 enum WindowType { 00028 RectangularWindow, 00029 BartlettWindow, 00030 HammingWindow, 00031 HanningWindow, 00032 BlackmanWindow, 00033 GaussianWindow, 00034 ParzenWindow, 00035 NuttallWindow, 00036 BlackmanHarrisWindow 00037 }; 00038 00039 template <typename T> 00040 class Window 00041 { 00042 public: 00050 Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); } 00051 Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); } 00052 Window &operator=(const Window &w) { 00053 if (&w == this) return *this; 00054 m_type = w.m_type; 00055 m_size = w.m_size; 00056 encache(); 00057 return *this; 00058 } 00059 virtual ~Window() { delete[] m_cache; } 00060 00061 void cut(T *src) const { cut(src, src); } 00062 void cut(T *src, T *dst) const { 00063 for (int i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i]; 00064 } 00065 00066 T getArea() { return m_area; } 00067 T getValue(int i) { return m_cache[i]; } 00068 00069 WindowType getType() const { return m_type; } 00070 int getSize() const { return m_size; } 00071 00072 // The names used by these functions are un-translated, for use in 00073 // e.g. XML I/O. Use Preferences::getPropertyValueLabel if you 00074 // want translated names for use in the user interface. 00075 static std::string getNameForType(WindowType type); 00076 static WindowType getTypeForName(std::string name); 00077 00078 protected: 00079 WindowType m_type; 00080 int m_size; 00081 T *m_cache; 00082 T m_area; 00083 00084 void encache(); 00085 void cosinewin(T *, T, T, T, T); 00086 }; 00087 00088 template <typename T> 00089 void Window<T>::encache() 00090 { 00091 const int n = m_size; 00092 T *mult = new T[n]; 00093 int i; 00094 for (i = 0; i < n; ++i) mult[i] = 1.0; 00095 00096 switch (m_type) { 00097 00098 case RectangularWindow: 00099 for (i = 0; i < n; ++i) { 00100 mult[i] *= 0.5; 00101 } 00102 break; 00103 00104 case BartlettWindow: 00105 for (i = 0; i < n/2; ++i) { 00106 mult[i] *= (i / T(n/2)); 00107 mult[i + n/2] *= (1.0 - (i / T(n/2))); 00108 } 00109 break; 00110 00111 case HammingWindow: 00112 cosinewin(mult, 0.54, 0.46, 0.0, 0.0); 00113 break; 00114 00115 case HanningWindow: 00116 cosinewin(mult, 0.50, 0.50, 0.0, 0.0); 00117 break; 00118 00119 case BlackmanWindow: 00120 cosinewin(mult, 0.42, 0.50, 0.08, 0.0); 00121 break; 00122 00123 case GaussianWindow: 00124 for (i = 0; i < n; ++i) { 00125 mult[i] *= pow(2, - pow((i - (n-1)/2.0) / ((n-1)/2.0 / 3), 2)); 00126 } 00127 break; 00128 00129 case ParzenWindow: 00130 { 00131 int N = n-1; 00132 for (i = 0; i < N/4; ++i) { 00133 T m = 2 * pow(1.0 - (T(N)/2 - i) / (T(N)/2), 3); 00134 mult[i] *= m; 00135 mult[N-i] *= m; 00136 } 00137 for (i = N/4; i <= N/2; ++i) { 00138 int wn = i - N/2; 00139 T m = 1.0 - 6 * pow(wn / (T(N)/2), 2) * (1.0 - abs(wn) / (T(N)/2)); 00140 mult[i] *= m; 00141 mult[N-i] *= m; 00142 } 00143 break; 00144 } 00145 00146 case NuttallWindow: 00147 cosinewin(mult, 0.3635819, 0.4891775, 0.1365995, 0.0106411); 00148 break; 00149 00150 case BlackmanHarrisWindow: 00151 cosinewin(mult, 0.35875, 0.48829, 0.14128, 0.01168); 00152 break; 00153 } 00154 00155 m_cache = mult; 00156 00157 m_area = 0; 00158 for (int i = 0; i < n; ++i) { 00159 m_area += m_cache[i]; 00160 } 00161 m_area /= n; 00162 } 00163 00164 template <typename T> 00165 void Window<T>::cosinewin(T *mult, T a0, T a1, T a2, T a3) 00166 { 00167 const int n = m_size; 00168 for (int i = 0; i < n; ++i) { 00169 mult[i] *= (a0 00170 - a1 * cos((2 * M_PI * i) / n) 00171 + a2 * cos((4 * M_PI * i) / n) 00172 - a3 * cos((6 * M_PI * i) / n)); 00173 } 00174 } 00175 00176 template <typename T> 00177 std::string 00178 Window<T>::getNameForType(WindowType type) 00179 { 00180 switch (type) { 00181 case RectangularWindow: return "rectangular"; 00182 case BartlettWindow: return "bartlett"; 00183 case HammingWindow: return "hamming"; 00184 case HanningWindow: return "hanning"; 00185 case BlackmanWindow: return "blackman"; 00186 case GaussianWindow: return "gaussian"; 00187 case ParzenWindow: return "parzen"; 00188 case NuttallWindow: return "nuttall"; 00189 case BlackmanHarrisWindow: return "blackman-harris"; 00190 } 00191 00192 std::cerr << "WARNING: Window::getNameForType: unknown type " 00193 << type << std::endl; 00194 00195 return "unknown"; 00196 } 00197 00198 template <typename T> 00199 WindowType 00200 Window<T>::getTypeForName(std::string name) 00201 { 00202 if (name == "rectangular") return RectangularWindow; 00203 if (name == "bartlett") return BartlettWindow; 00204 if (name == "hamming") return HammingWindow; 00205 if (name == "hanning") return HanningWindow; 00206 if (name == "blackman") return BlackmanWindow; 00207 if (name == "gaussian") return GaussianWindow; 00208 if (name == "parzen") return ParzenWindow; 00209 if (name == "nuttall") return NuttallWindow; 00210 if (name == "blackman-harris") return BlackmanHarrisWindow; 00211 00212 std::cerr << "WARNING: Window::getTypeForName: unknown name \"" 00213 << name << "\", defaulting to \"hanning\"" << std::endl; 00214 00215 return HanningWindow; 00216 } 00217 00218 #endif