Mercurial > hg > svgui
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; |