diff layer/SpectrogramLayer.cpp @ 1212:a1ee3108d1d3 3.0-integration

Make the colour 3d plot renderer able to support more than one level of peak cache; introduce a second "peak" cache for the spectrogram layer that actually has a 1-1 column relationship with the underlying FFT model, and use it in addition to the existing peak cache if memory is plentiful. Makes spectrograms appear much faster in many common situations.
author Chris Cannam
date Thu, 05 Jan 2017 14:02:54 +0000
parents 7a19738b9762
children de1792daae07
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Thu Jan 05 11:10:57 2017 +0000
+++ b/layer/SpectrogramLayer.cpp	Thu Jan 05 14:02:54 2017 +0000
@@ -25,6 +25,8 @@
 #include "base/LogRange.h"
 #include "base/ColumnOp.h"
 #include "base/Strings.h"
+#include "base/StorageAdviser.h"
+#include "base/Exceptions.h"
 #include "widgets/CommandHistory.h"
 #include "data/model/Dense3DModelPeakCache.h"
 
@@ -80,6 +82,7 @@
     m_haveDetailedScale(false),
     m_exiting(false),
     m_fftModel(0),
+    m_wholeCache(0),
     m_peakCache(0),
     m_peakCacheDivisor(8)
 {
@@ -132,6 +135,7 @@
 
     delete m_fftModel;
     delete m_peakCache;
+    delete m_wholeCache;
 }
 
 pair<ColourScaleType, double>
@@ -743,8 +747,6 @@
     recreateFFTModel();
 
     emit layerParametersChanged();
-
-//    fillCache();
 }
 
 int
@@ -1339,8 +1341,10 @@
         emit sliceableModelReplaced(m_fftModel, 0);
         delete m_fftModel;
         delete m_peakCache;
+        delete m_wholeCache;
         m_fftModel = 0;
         m_peakCache = 0;
+        m_wholeCache = 0;
         return;
     }
 
@@ -1355,6 +1359,9 @@
 
     delete m_peakCache;
     m_peakCache = 0;
+
+    delete m_wholeCache;
+    m_wholeCache = 0;
     
     if (!m_fftModel->isOK()) {
         QMessageBox::critical
@@ -1365,14 +1372,53 @@
         m_fftModel = 0;
         return;
     }
-    
-    m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor);
+
+    if (canStoreWholeCache()) { // i.e. if enough memory
+        m_wholeCache = new Dense3DModelPeakCache(m_fftModel, 1);
+        m_peakCache = new Dense3DModelPeakCache(m_wholeCache, m_peakCacheDivisor);
+    } else {
+        m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor);
+    }
 
     emit sliceableModelReplaced(oldModel, m_fftModel);
 
     delete oldModel;
 }
 
+bool
+SpectrogramLayer::canStoreWholeCache() const
+{
+    if (!m_fftModel) {
+        return false; // or true, doesn't really matter
+    }
+
+    size_t sz =
+        size_t(m_fftModel->getWidth()) *
+        size_t(m_fftModel->getHeight()) *
+        sizeof(float);
+
+    try {
+        SVDEBUG << "Requesting advice from StorageAdviser on whether to create whole-model cache" << endl;
+        StorageAdviser::Recommendation recommendation =
+            StorageAdviser::recommend
+            (StorageAdviser::Criteria(StorageAdviser::SpeedCritical |
+                                      StorageAdviser::PrecisionCritical |
+                                      StorageAdviser::FrequentLookupLikely),
+             sz / 1024, sz / 1024);
+        if ((recommendation & StorageAdviser::UseDisc) ||
+            (recommendation & StorageAdviser::ConserveSpace)) {
+            SVDEBUG << "Seems inadvisable to create whole-model cache" << endl;
+            return false;
+        } else {
+            SVDEBUG << "Seems fine to create whole-model cache" << endl;
+            return true;
+        }
+    } catch (const InsufficientDiscSpace &) {
+        SVDEBUG << "Seems like a terrible idea to create whole-model cache" << endl;
+        return false;
+    }
+}
+
 const Model *
 SpectrogramLayer::getSliceableModel() const
 {
@@ -1405,7 +1451,8 @@
         sources.verticalBinLayer = this;
         sources.fft = getFFTModel();
         sources.source = sources.fft;
-        sources.peakCache = getPeakCache();
+        if (m_peakCache) sources.peakCaches.push_back(m_peakCache);
+        if (m_wholeCache) sources.peakCaches.push_back(m_wholeCache);
 
         ColourScale::Parameters cparams;
         cparams.colourMap = m_colourMap;