svcore  1.9
Window.h
Go to the documentation of this file.
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