changeset 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 804dd0c06f0e
children 403e961ec6ab
files base/ColumnOp.cpp base/ColumnOp.h base/Extents.h base/test/TestColumnOp.h data/model/Dense3DModelPeakCache.h data/model/FFTModel.cpp data/model/FFTModel.h transform/FeatureExtractionModelTransformer.cpp
diffstat 8 files changed, 51 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/base/ColumnOp.cpp	Mon Apr 06 13:55:44 2020 +0100
+++ b/base/ColumnOp.cpp	Thu Apr 09 11:22:55 2020 +0100
@@ -32,7 +32,7 @@
 ColumnOp::Column
 ColumnOp::peakPick(const Column &in)
 {
-    vector<float> out(in.size(), 0.f);
+    Column out(in.size(), 0.f);
 
     for (int i = 0; in_range_for(in, i); ++i) {
         if (isPeak(in, i)) {
@@ -119,7 +119,7 @@
                      int minbin,
                      bool interpolate)
 {
-    vector<float> out(h, 0.f);
+    Column out(h, 0.f);
     int bins = int(in.size());
 
     if (interpolate) {
--- a/base/ColumnOp.h	Mon Apr 06 13:55:44 2020 +0100
+++ b/base/ColumnOp.h	Thu Apr 09 11:22:55 2020 +0100
@@ -53,7 +53,7 @@
     /** 
      * Column type. 
      */
-    typedef std::vector<float> Column;
+    typedef floatvec_t Column;
 
     /**
      * Scale the given column using the given gain multiplier.
--- a/base/Extents.h	Mon Apr 06 13:55:44 2020 +0100
+++ b/base/Extents.h	Thu Apr 09 11:22:55 2020 +0100
@@ -59,7 +59,8 @@
         }
         return changed;
     }
-    bool sample(const std::vector<T> &ff) {
+    template <typename Alloc>
+    bool sample(const std::vector<T, Alloc> &ff) {
         bool changed = false;
         for (auto f: ff) {
             if (sample(f)) {
--- a/base/test/TestColumnOp.h	Mon Apr 06 13:55:44 2020 +0100
+++ b/base/test/TestColumnOp.h	Thu Apr 09 11:22:55 2020 +0100
@@ -36,8 +36,8 @@
     typedef vector<double> BinMapping;
 
 #ifdef REPORT
-    template <typename T>
-    void report(vector<T> v) {
+    template <typename T, typename Alloc>
+    void report(vector<T, Alloc> v) {
         cerr << "Vector is: [ ";
         for (int i = 0; i < int(v.size()); ++i) {
             if (i > 0) cerr << ", ";
@@ -46,8 +46,8 @@
         cerr << " ]\n";
     }
 #else
-    template <typename T>
-    void report(vector<T> ) { }
+    template <typename T, typename Alloc>
+    void report(vector<T, Alloc> ) { }
 #endif
                                      
 private slots:
--- a/data/model/Dense3DModelPeakCache.h	Mon Apr 06 13:55:44 2020 +0100
+++ b/data/model/Dense3DModelPeakCache.h	Thu Apr 09 11:22:55 2020 +0100
@@ -136,7 +136,7 @@
     ModelId m_source;
     int m_columnsPerPeak;
 
-    mutable std::vector<std::vector<float>> m_cache;
+    mutable std::vector<Column> m_cache;
     mutable std::vector<bool> m_coverage; // bool for space efficiency
                                           // (vector of bool is a bitmap)
     mutable bool m_finalColumnIncomplete;
--- 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
--- a/data/model/FFTModel.h	Mon Apr 06 13:55:44 2020 +0100
+++ b/data/model/FFTModel.h	Thu Apr 09 11:22:55 2020 +0100
@@ -193,28 +193,26 @@
         return { startFrame, endFrame };
     }
 
-    typedef std::vector<float, breakfastquay::StlAllocator<float>> fvec;
-    typedef std::vector<std::complex<float>,
-                        breakfastquay::StlAllocator<std::complex<float>>> cvec;
-
-    cvec getFFTColumn(int column) const;
-    fvec getSourceSamples(int column) const;
-    fvec getSourceData(std::pair<sv_frame_t, sv_frame_t>) const;
-    fvec getSourceDataUncached(std::pair<sv_frame_t, sv_frame_t>) const;
+    const complexvec_t &getFFTColumn(int column) const;
+    floatvec_t getSourceSamples(int column) const;
+    floatvec_t getSourceData(std::pair<sv_frame_t, sv_frame_t>) const;
+    floatvec_t getSourceDataUncached(std::pair<sv_frame_t, sv_frame_t>) const;
 
     struct SavedSourceData {
         std::pair<sv_frame_t, sv_frame_t> range;
-        fvec data;
+        floatvec_t data;
     };
     mutable SavedSourceData m_savedData;
 
     struct SavedColumn {
         int n;
-        cvec col;
+        complexvec_t col;
     };
     mutable std::vector<SavedColumn> m_cached;
     mutable size_t m_cacheWriteIndex;
     size_t m_cacheSize;
+
+    void clearCaches();
 };
 
 #endif
--- a/transform/FeatureExtractionModelTransformer.cpp	Mon Apr 06 13:55:44 2020 +0100
+++ b/transform/FeatureExtractionModelTransformer.cpp	Thu Apr 09 11:22:55 2020 +0100
@@ -1156,7 +1156,9 @@
             <BasicCompressedDenseThreeDimensionalModel>(outputId);
         if (!model) return;
         
-        DenseThreeDimensionalModel::Column values = feature.values;
+        DenseThreeDimensionalModel::Column values;
+        values.insert(values.begin(),
+                      feature.values.begin(), feature.values.end());
         
         if (!feature.hasTimestamp && m_fixedRateFeatureNos[n] >= 0) {
             model->setColumn(m_fixedRateFeatureNos[n], values);