update qm-dsp library
[ardour.git] / libs / qm-dsp / base / Window.h
index 02ca426d66dd253c1a2871e356b727d46bd5ad75..93909115c0ed4e6ad6b95300cc309b3da0c43aa5 100644 (file)
@@ -18,6 +18,7 @@
 #include <cmath>
 #include <iostream>
 #include <map>
+#include <vector>
 
 enum WindowType {
     RectangularWindow,
@@ -25,18 +26,28 @@ enum WindowType {
     HammingWindow,
     HanningWindow,
     BlackmanWindow,
-    GaussianWindow,
-    ParzenWindow
+    BlackmanHarrisWindow,
+
+    FirstWindow = RectangularWindow,
+    LastWindow = BlackmanHarrisWindow
 };
 
+/**
+ * Various shaped windows for sample frame conditioning, including
+ * cosine windows (Hann etc) and triangular and rectangular windows.
+ */
 template <typename T>
 class Window
 {
 public:
     /**
-     * Construct a windower of the given type.
+     * Construct a windower of the given type and size. 
+     *
+     * Note that the cosine windows are periodic by design, rather
+     * than symmetrical. (A window of size N is equivalent to a
+     * symmetrical window of size N+1 with the final element missing.)
      */
-    Window(WindowType type, size_t size) : m_type(type), m_size(size) { encache(); }
+    Window(WindowType type, int size) : m_type(type), m_size(size) { encache(); }
     Window(const Window &w) : m_type(w.m_type), m_size(w.m_size) { encache(); }
     Window &operator=(const Window &w) {
        if (&w == this) return *this;
@@ -46,79 +57,98 @@ public:
        return *this;
     }
     virtual ~Window() { delete[] m_cache; }
-
+    
     void cut(T *src) const { cut(src, src); }
     void cut(const T *src, T *dst) const {
-       for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
+       for (int i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
     }
 
     WindowType getType() const { return m_type; }
-    size_t getSize() const { return m_size; }
+    int getSize() const { return m_size; }
+
+    std::vector<T> getWindowData() const {
+        std::vector<T> d;
+        for (int i = 0; i < m_size; ++i) {
+            d.push_back(m_cache[i]);
+        }
+        return d;
+    }
 
 protected:
     WindowType m_type;
-    size_t m_size;
+    int m_size;
     T *m_cache;
-
+    
     void encache();
 };
 
 template <typename T>
 void Window<T>::encache()
 {
-    size_t n = m_size;
+    int n = m_size;
     T *mult = new T[n];
-    size_t i;
+    int i;
     for (i = 0; i < n; ++i) mult[i] = 1.0;
 
     switch (m_type) {
-
+               
     case RectangularWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * 0.5;
+        for (i = 0; i < n; ++i) {
+            mult[i] = mult[i] * 0.5;
        }
        break;
-
+           
     case BartlettWindow:
-       for (i = 0; i < n/2; ++i) {
-           mult[i] = mult[i] * (i / T(n/2));
-           mult[i + n/2] = mult[i + n/2] * (1.0 - (i / T(n/2)));
+        if (n == 2) {
+            mult[0] = mult[1] = 0; // "matlab compatible"
+        } else if (n == 3) {
+            mult[0] = 0;
+            mult[1] = mult[2] = 2./3.;
+        } else if (n > 3) {
+            for (i = 0; i < n/2; ++i) {
+                mult[i] = mult[i] * (i / T(n/2));
+                mult[i + n - n/2] = mult[i + n - n/2] * (1.0 - (i / T(n/2)));
+            }
        }
        break;
-
+           
     case HammingWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * (0.54 - 0.46 * cos(2 * M_PI * i / n));
+        if (n > 1) {
+            for (i = 0; i < n; ++i) {
+                mult[i] = mult[i] * (0.54 - 0.46 * cos(2 * M_PI * i / n));
+            }
        }
        break;
-
+           
     case HanningWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * (0.50 - 0.50 * cos(2 * M_PI * i / n));
+        if (n > 1) {
+            for (i = 0; i < n; ++i) {
+                mult[i] = mult[i] * (0.50 - 0.50 * cos(2 * M_PI * i / n));
+            }
        }
        break;
-
+           
     case BlackmanWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * (0.42 - 0.50 * cos(2 * M_PI * i / n)
-                                + 0.08 * cos(4 * M_PI * i / n));
+        if (n > 1) {
+            for (i = 0; i < n; ++i) {
+                mult[i] = mult[i] * (0.42 - 0.50 * cos(2 * M_PI * i / n)
+                                     + 0.08 * cos(4 * M_PI * i / n));
+            }
        }
        break;
-
-    case GaussianWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * exp((-1.0 / (n*n)) * ((T(2*i) - n) *
-                                                     (T(2*i) - n)));
-       }
-       break;
-
-    case ParzenWindow:
-       for (i = 0; i < n; ++i) {
-           mult[i] = mult[i] * (1.0 - fabs((T(2*i) - n) / T(n + 1)));
+           
+    case BlackmanHarrisWindow:
+        if (n > 1) {
+            for (i = 0; i < n; ++i) {
+                mult[i] = mult[i] * (0.35875
+                                     - 0.48829 * cos(2 * M_PI * i / n)
+                                     + 0.14128 * cos(4 * M_PI * i / n)
+                                     - 0.01168 * cos(6 * M_PI * i / n));
+            }
        }
        break;
     }
-
+          
     m_cache = mult;
 }