comparison 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
comparison
equal deleted inserted replaced
1211:7a19738b9762 1212:a1ee3108d1d3
23 #include "base/Preferences.h" 23 #include "base/Preferences.h"
24 #include "base/RangeMapper.h" 24 #include "base/RangeMapper.h"
25 #include "base/LogRange.h" 25 #include "base/LogRange.h"
26 #include "base/ColumnOp.h" 26 #include "base/ColumnOp.h"
27 #include "base/Strings.h" 27 #include "base/Strings.h"
28 #include "base/StorageAdviser.h"
29 #include "base/Exceptions.h"
28 #include "widgets/CommandHistory.h" 30 #include "widgets/CommandHistory.h"
29 #include "data/model/Dense3DModelPeakCache.h" 31 #include "data/model/Dense3DModelPeakCache.h"
30 32
31 #include "ColourMapper.h" 33 #include "ColourMapper.h"
32 #include "PianoScale.h" 34 #include "PianoScale.h"
78 m_lastEmittedZoomStep(-1), 80 m_lastEmittedZoomStep(-1),
79 m_synchronous(false), 81 m_synchronous(false),
80 m_haveDetailedScale(false), 82 m_haveDetailedScale(false),
81 m_exiting(false), 83 m_exiting(false),
82 m_fftModel(0), 84 m_fftModel(0),
85 m_wholeCache(0),
83 m_peakCache(0), 86 m_peakCache(0),
84 m_peakCacheDivisor(8) 87 m_peakCacheDivisor(8)
85 { 88 {
86 QString colourConfigName = "spectrogram-colour"; 89 QString colourConfigName = "spectrogram-colour";
87 int colourConfigDefault = int(ColourMapper::Green); 90 int colourConfigDefault = int(ColourMapper::Green);
130 { 133 {
131 invalidateRenderers(); 134 invalidateRenderers();
132 135
133 delete m_fftModel; 136 delete m_fftModel;
134 delete m_peakCache; 137 delete m_peakCache;
138 delete m_wholeCache;
135 } 139 }
136 140
137 pair<ColourScaleType, double> 141 pair<ColourScaleType, double>
138 SpectrogramLayer::convertToColourScale(int value) 142 SpectrogramLayer::convertToColourScale(int value)
139 { 143 {
741 m_windowHopLevel = v; 745 m_windowHopLevel = v;
742 746
743 recreateFFTModel(); 747 recreateFFTModel();
744 748
745 emit layerParametersChanged(); 749 emit layerParametersChanged();
746
747 // fillCache();
748 } 750 }
749 751
750 int 752 int
751 SpectrogramLayer::getWindowHopLevel() const 753 SpectrogramLayer::getWindowHopLevel() const
752 { 754 {
1337 1339
1338 if (!m_model || !m_model->isOK()) { 1340 if (!m_model || !m_model->isOK()) {
1339 emit sliceableModelReplaced(m_fftModel, 0); 1341 emit sliceableModelReplaced(m_fftModel, 0);
1340 delete m_fftModel; 1342 delete m_fftModel;
1341 delete m_peakCache; 1343 delete m_peakCache;
1344 delete m_wholeCache;
1342 m_fftModel = 0; 1345 m_fftModel = 0;
1343 m_peakCache = 0; 1346 m_peakCache = 0;
1347 m_wholeCache = 0;
1344 return; 1348 return;
1345 } 1349 }
1346 1350
1347 FFTModel *oldModel = m_fftModel; 1351 FFTModel *oldModel = m_fftModel;
1348 1352
1353 getWindowIncrement(), 1357 getWindowIncrement(),
1354 getFFTSize()); 1358 getFFTSize());
1355 1359
1356 delete m_peakCache; 1360 delete m_peakCache;
1357 m_peakCache = 0; 1361 m_peakCache = 0;
1362
1363 delete m_wholeCache;
1364 m_wholeCache = 0;
1358 1365
1359 if (!m_fftModel->isOK()) { 1366 if (!m_fftModel->isOK()) {
1360 QMessageBox::critical 1367 QMessageBox::critical
1361 (0, tr("FFT cache failed"), 1368 (0, tr("FFT cache failed"),
1362 tr("Failed to create the FFT model for this spectrogram.\n" 1369 tr("Failed to create the FFT model for this spectrogram.\n"
1363 "There may be insufficient memory or disc space to continue.")); 1370 "There may be insufficient memory or disc space to continue."));
1364 delete m_fftModel; 1371 delete m_fftModel;
1365 m_fftModel = 0; 1372 m_fftModel = 0;
1366 return; 1373 return;
1367 } 1374 }
1368 1375
1369 m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor); 1376 if (canStoreWholeCache()) { // i.e. if enough memory
1377 m_wholeCache = new Dense3DModelPeakCache(m_fftModel, 1);
1378 m_peakCache = new Dense3DModelPeakCache(m_wholeCache, m_peakCacheDivisor);
1379 } else {
1380 m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor);
1381 }
1370 1382
1371 emit sliceableModelReplaced(oldModel, m_fftModel); 1383 emit sliceableModelReplaced(oldModel, m_fftModel);
1372 1384
1373 delete oldModel; 1385 delete oldModel;
1386 }
1387
1388 bool
1389 SpectrogramLayer::canStoreWholeCache() const
1390 {
1391 if (!m_fftModel) {
1392 return false; // or true, doesn't really matter
1393 }
1394
1395 size_t sz =
1396 size_t(m_fftModel->getWidth()) *
1397 size_t(m_fftModel->getHeight()) *
1398 sizeof(float);
1399
1400 try {
1401 SVDEBUG << "Requesting advice from StorageAdviser on whether to create whole-model cache" << endl;
1402 StorageAdviser::Recommendation recommendation =
1403 StorageAdviser::recommend
1404 (StorageAdviser::Criteria(StorageAdviser::SpeedCritical |
1405 StorageAdviser::PrecisionCritical |
1406 StorageAdviser::FrequentLookupLikely),
1407 sz / 1024, sz / 1024);
1408 if ((recommendation & StorageAdviser::UseDisc) ||
1409 (recommendation & StorageAdviser::ConserveSpace)) {
1410 SVDEBUG << "Seems inadvisable to create whole-model cache" << endl;
1411 return false;
1412 } else {
1413 SVDEBUG << "Seems fine to create whole-model cache" << endl;
1414 return true;
1415 }
1416 } catch (const InsufficientDiscSpace &) {
1417 SVDEBUG << "Seems like a terrible idea to create whole-model cache" << endl;
1418 return false;
1419 }
1374 } 1420 }
1375 1421
1376 const Model * 1422 const Model *
1377 SpectrogramLayer::getSliceableModel() const 1423 SpectrogramLayer::getSliceableModel() const
1378 { 1424 {
1403 1449
1404 Colour3DPlotRenderer::Sources sources; 1450 Colour3DPlotRenderer::Sources sources;
1405 sources.verticalBinLayer = this; 1451 sources.verticalBinLayer = this;
1406 sources.fft = getFFTModel(); 1452 sources.fft = getFFTModel();
1407 sources.source = sources.fft; 1453 sources.source = sources.fft;
1408 sources.peakCache = getPeakCache(); 1454 if (m_peakCache) sources.peakCaches.push_back(m_peakCache);
1455 if (m_wholeCache) sources.peakCaches.push_back(m_wholeCache);
1409 1456
1410 ColourScale::Parameters cparams; 1457 ColourScale::Parameters cparams;
1411 cparams.colourMap = m_colourMap; 1458 cparams.colourMap = m_colourMap;
1412 cparams.scaleType = m_colourScale; 1459 cparams.scaleType = m_colourScale;
1413 cparams.multiple = m_colourScaleMultiple; 1460 cparams.multiple = m_colourScaleMultiple;