diff data/model/FFTModel.cpp @ 1837:1b688ab5f1b3

Unify various vectors to our base floatvec_t type; store columns in fft model cache at their desired height so we can return a reference (speeding up the peak-frequency spectrogram in particular)
author Chris Cannam
date Thu, 09 Apr 2020 11:22:55 +0100
parents dd51797e528e
children 915d316a5609
line wrap: on
line diff
--- a/data/model/FFTModel.cpp	Mon Apr 06 13:55:44 2020 +0100
+++ b/data/model/FFTModel.cpp	Thu Apr 09 11:22:55 2020 +0100
@@ -51,9 +51,7 @@
     m_cacheWriteIndex(0),
     m_cacheSize(3)
 {
-    while (m_cached.size() < m_cacheSize) {
-        m_cached.push_back({ -1, cvec(m_fftSize / 2 + 1) });
-    }
+    clearCaches();
     
     if (m_windowSize > m_fftSize) {
         SVCERR << "ERROR: FFTModel::FFTModel: window size (" << m_windowSize
@@ -80,6 +78,17 @@
 {
 }
 
+void
+FFTModel::clearCaches()
+{
+    m_cached.clear();
+    while (m_cached.size() < m_cacheSize) {
+        m_cached.push_back({ -1, complexvec_t(m_fftSize / 2 + 1) });
+    }
+    m_cacheWriteIndex = 0;
+    m_savedData.range = { 0, 0 };
+}
+
 bool
 FFTModel::isOK() const
 {
@@ -110,6 +119,7 @@
 FFTModel::setMaximumFrequency(double freq)
 {
     m_maximumFrequency = freq;
+    clearCaches();
 }
 
 int
@@ -246,7 +256,7 @@
     return true;
 }
 
-FFTModel::fvec
+floatvec_t
 FFTModel::getSourceSamples(int column) const
 {
     // m_fftSize may be greater than m_windowSize, but not the reverse
@@ -262,7 +272,7 @@
         return data;
     } else {
         vector<float> pad(off, 0.f);
-        fvec padded;
+        floatvec_t padded;
         padded.reserve(m_fftSize);
         padded.insert(padded.end(), pad.begin(), pad.end());
         padded.insert(padded.end(), data.begin(), data.end());
@@ -271,7 +281,7 @@
     }
 }
 
-FFTModel::fvec
+floatvec_t
 FFTModel::getSourceData(pair<sv_frame_t, sv_frame_t> range) const
 {
 //    cerr << "getSourceData(" << range.first << "," << range.second
@@ -293,14 +303,14 @@
         
         sv_frame_t discard = range.first - m_savedData.range.first;
 
-        fvec data;
+        floatvec_t data;
         data.reserve(range.second - range.first);
 
         data.insert(data.end(),
                     m_savedData.data.begin() + discard,
                     m_savedData.data.end());
 
-        fvec rest = getSourceDataUncached
+        floatvec_t rest = getSourceDataUncached
             ({ m_savedData.range.second, range.second });
 
         data.insert(data.end(), rest.begin(), rest.end());
@@ -318,7 +328,7 @@
     }
 }
 
-FFTModel::fvec
+floatvec_t
 FFTModel::getSourceDataUncached(pair<sv_frame_t, sv_frame_t> range) const
 {
     Profiler profiler("FFTModel::getSourceDataUncached");
@@ -366,12 +376,9 @@
     return data;
 }
 
-FFTModel::cvec
+const complexvec_t &
 FFTModel::getFFTColumn(int n) const
 {
-    int h = getHeight();
-    bool truncate = (h < m_fftSize / 2 + 1);
-    
     // The small cache (i.e. the m_cached deque) is for cases where
     // values are looked up individually, and for e.g. peak-frequency
     // spectrograms where values from two consecutive columns are
@@ -381,11 +388,7 @@
     for (const auto &incache : m_cached) {
         if (incache.n == n) {
             inSmallCache.hit();
-            if (!truncate) {
-                return incache.col;
-            } else {
-                return cvec(incache.col.begin(), incache.col.begin() + h);
-            }
+            return incache.col;
         }
     }
     inSmallCache.miss();
@@ -396,20 +399,23 @@
     m_windower.cut(samples.data() + (m_fftSize - m_windowSize) / 2);
     breakfastquay::v_fftshift(samples.data(), m_fftSize);
 
-    cvec &col = m_cached[m_cacheWriteIndex].col;
+    complexvec_t &col = m_cached[m_cacheWriteIndex].col;
+
+    // expand to large enough for fft destination, if truncated previously
+    col.resize(m_fftSize / 2 + 1);
     
     m_fft.forwardInterleaved(samples.data(),
                              reinterpret_cast<float *>(col.data()));
 
+    // keep only the number of elements we need - so that we can
+    // return a const ref without having to resize on a cache hit
+    col.resize(getHeight());
+
     m_cached[m_cacheWriteIndex].n = n;
 
     m_cacheWriteIndex = (m_cacheWriteIndex + 1) % m_cacheSize;
 
-    if (!truncate) {
-        return col;
-    } else {
-        return cvec(col.begin(), col.begin() + h);
-    }
+    return col;
 }
 
 bool