changeset 1093:44b079427b36 simple-fft-model

Make a small cache of recently-used columns
author Chris Cannam
date Fri, 12 Jun 2015 18:50:52 +0100
parents 70f18770b72d
children b386363ff6c8
files data/fft/FFTapi.h data/model/FFTModel.cpp data/model/FFTModel.h
diffstat 3 files changed, 39 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/data/fft/FFTapi.h	Fri Jun 12 18:20:09 2015 +0100
+++ b/data/fft/FFTapi.h	Fri Jun 12 18:50:52 2015 +0100
@@ -79,7 +79,7 @@
         std::vector<std::complex<float> > result;
         result.reserve(hs + 1);
         for (int i = 0; i <= hs; ++i) {
-            result[i] = { m_output[i][0], m_output[i][1] };
+            result.push_back({ m_output[i][0], m_output[i][1] });
         }
         return result;
     }
--- a/data/model/FFTModel.cpp	Fri Jun 12 18:20:09 2015 +0100
+++ b/data/model/FFTModel.cpp	Fri Jun 12 18:50:52 2015 +0100
@@ -43,7 +43,8 @@
     m_windowIncrement(windowIncrement),
     m_fftSize(fftSize),
     m_windower(windowType, windowSize),
-    m_fft(fftSize)
+    m_fft(fftSize),
+    m_cacheSize(3)
 {
     if (m_windowSize > m_fftSize) {
         cerr << "ERROR: FFTModel::FFTModel: window size (" << m_windowSize
@@ -101,8 +102,9 @@
 float
 FFTModel::getMagnitudeAt(int x, int y) const
 {
-    //!!! 
-    return abs(getFFTColumn(x)[y]);
+    if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) return 0.f;
+    auto col = getFFTColumn(x);
+    return abs(col[y]);
 }
 
 float
@@ -119,7 +121,7 @@
 float
 FFTModel::getPhaseAt(int x, int y) const
 {
-    //!!! 
+    if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) return 0.f;
     return arg(getFFTColumn(x)[y]);
 }
 
@@ -132,7 +134,7 @@
 }
 
 bool
-FFTModel::isColumnAvailable(int ) const
+FFTModel::isColumnAvailable(int) const
 {
     //!!!
     return true;
@@ -218,11 +220,25 @@
 }
 
 vector<complex<float>>
-FFTModel::getFFTColumn(int column) const
+FFTModel::getFFTColumn(int n) const
 {
-    auto samples = getSourceSamples(column);
+    for (auto &incache : m_cached) {
+        if (incache.n == n) {
+            return incache.col;
+        }
+    }
+    
+    auto samples = getSourceSamples(n);
     m_windower.cut(&samples[0]);
-    return m_fft.process(samples);
+    auto col = m_fft.process(samples);
+
+    SavedColumn sc { n, col };
+    if (m_cached.size() >= m_cacheSize) {
+        m_cached.pop_front();
+    }
+    m_cached.push_back(sc);
+
+    return col;
 }
 
 bool
--- a/data/model/FFTModel.h	Fri Jun 12 18:20:09 2015 +0100
+++ b/data/model/FFTModel.h	Fri Jun 12 18:50:52 2015 +0100
@@ -24,9 +24,9 @@
 #include "data/fft/FFTapi.h"
 
 #include <set>
-#include <map>
 #include <vector>
 #include <complex>
+#include <deque>
 
 /**
  * An implementation of DenseThreeDimensionalModel that makes FFT data
@@ -80,7 +80,9 @@
     virtual bool shouldUseLogValueScale() const { return true; }
     virtual int getCompletion() const {
         int c = 100;
-        if (m_model) (void)m_model->isReady(&c);
+        if (m_model) {
+            if (m_model->isReady(&c)) return 100;
+        }
         return c;
     }
     virtual QString getError() const { return ""; } //!!!???
@@ -166,6 +168,16 @@
 
     std::vector<std::complex<float> > getFFTColumn(int column) const;
     std::vector<float> getSourceSamples(int column) const;
+
+    struct SavedColumn {
+        int n;
+        std::vector<std::complex<float> > col;
+    };
+    
+    mutable std::deque<SavedColumn> m_cached;
+    size_t m_cacheSize;
+
+    //!!! also optionally cache polar?
 };
 
 #endif