comparison layer/SpectrogramLayer.cpp @ 1473:886c1cd48f9d by-id

Further layer updates for ModelById
author Chris Cannam
date Tue, 02 Jul 2019 11:49:52 +0100
parents dbff4b290bf0
children e540aa5d89cd
comparison
equal deleted inserted replaced
1472:dbff4b290bf0 1473:886c1cd48f9d
80 m_normalizeVisibleArea(false), 80 m_normalizeVisibleArea(false),
81 m_lastEmittedZoomStep(-1), 81 m_lastEmittedZoomStep(-1),
82 m_synchronous(false), 82 m_synchronous(false),
83 m_haveDetailedScale(false), 83 m_haveDetailedScale(false),
84 m_exiting(false), 84 m_exiting(false),
85 m_wholeCache(nullptr),
86 m_peakCache(nullptr),
87 m_peakCacheDivisor(8) 85 m_peakCacheDivisor(8)
88 { 86 {
89 QString colourConfigName = "spectrogram-colour"; 87 QString colourConfigName = "spectrogram-colour";
90 int colourConfigDefault = int(ColourMapper::Green); 88 int colourConfigDefault = int(ColourMapper::Green);
91 89
136 } 134 }
137 135
138 void 136 void
139 SpectrogramLayer::deleteDerivedModels() 137 SpectrogramLayer::deleteDerivedModels()
140 { 138 {
141 if (m_fftModel) m_fftModel->aboutToDelete(); 139 ModelById::release(m_fftModel);
142 if (m_peakCache) m_peakCache->aboutToDelete(); 140 ModelById::release(m_peakCache);
143 if (m_wholeCache) m_wholeCache->aboutToDelete(); 141 ModelById::release(m_wholeCache);
144 142
145 delete m_fftModel; 143 m_fftModel = {};
146 delete m_peakCache; 144 m_peakCache = {};
147 delete m_wholeCache; 145 m_wholeCache = {};
148
149 m_fftModel = nullptr;
150 m_peakCache = nullptr;
151 m_wholeCache = nullptr;
152 } 146 }
153 147
154 pair<ColourScaleType, double> 148 pair<ColourScaleType, double>
155 SpectrogramLayer::convertToColourScale(int value) 149 SpectrogramLayer::convertToColourScale(int value)
156 { 150 {
1105 } 1099 }
1106 1100
1107 double 1101 double
1108 SpectrogramLayer::getEffectiveMinFrequency() const 1102 SpectrogramLayer::getEffectiveMinFrequency() const
1109 { 1103 {
1110 sv_samplerate_t sr = m_model->getSampleRate(); 1104 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1105 if (!model) return 0.0;
1106
1107 sv_samplerate_t sr = model->getSampleRate();
1111 double minf = double(sr) / getFFTSize(); 1108 double minf = double(sr) / getFFTSize();
1112 1109
1113 if (m_minFrequency > 0.0) { 1110 if (m_minFrequency > 0.0) {
1114 int minbin = int((double(m_minFrequency) * getFFTSize()) / sr + 0.01); 1111 int minbin = int((double(m_minFrequency) * getFFTSize()) / sr + 0.01);
1115 if (minbin < 1) minbin = 1; 1112 if (minbin < 1) minbin = 1;
1120 } 1117 }
1121 1118
1122 double 1119 double
1123 SpectrogramLayer::getEffectiveMaxFrequency() const 1120 SpectrogramLayer::getEffectiveMaxFrequency() const
1124 { 1121 {
1125 sv_samplerate_t sr = m_model->getSampleRate(); 1122 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1123 if (!model) return 0.0;
1124
1125 sv_samplerate_t sr = model->getSampleRate();
1126 double maxf = double(sr) / 2; 1126 double maxf = double(sr) / 2;
1127 1127
1128 if (m_maxFrequency > 0.0) { 1128 if (m_maxFrequency > 0.0) {
1129 int maxbin = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); 1129 int maxbin = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1);
1130 if (maxbin > getFFTSize() / 2) maxbin = getFFTSize() / 2; 1130 if (maxbin > getFFTSize() / 2) maxbin = getFFTSize() / 2;
1146 } 1146 }
1147 1147
1148 double 1148 double
1149 SpectrogramLayer::getYForBin(const LayerGeometryProvider *v, double bin) const 1149 SpectrogramLayer::getYForBin(const LayerGeometryProvider *v, double bin) const
1150 { 1150 {
1151 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1152 if (!model) return 0.0;
1153
1151 double minf = getEffectiveMinFrequency(); 1154 double minf = getEffectiveMinFrequency();
1152 double maxf = getEffectiveMaxFrequency(); 1155 double maxf = getEffectiveMaxFrequency();
1153 bool logarithmic = (m_binScale == BinScale::Log); 1156 bool logarithmic = (m_binScale == BinScale::Log);
1154 sv_samplerate_t sr = m_model->getSampleRate(); 1157 sv_samplerate_t sr = model->getSampleRate();
1155 1158
1156 double freq = (bin * sr) / getFFTSize(); 1159 double freq = (bin * sr) / getFFTSize();
1157 1160
1158 double y = v->getYForFrequency(freq, minf, maxf, logarithmic); 1161 double y = v->getYForFrequency(freq, minf, maxf, logarithmic);
1159 1162
1161 } 1164 }
1162 1165
1163 double 1166 double
1164 SpectrogramLayer::getBinForY(const LayerGeometryProvider *v, double y) const 1167 SpectrogramLayer::getBinForY(const LayerGeometryProvider *v, double y) const
1165 { 1168 {
1166 sv_samplerate_t sr = m_model->getSampleRate(); 1169 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1170 if (!model) return 0.0;
1171
1172 sv_samplerate_t sr = model->getSampleRate();
1167 double minf = getEffectiveMinFrequency(); 1173 double minf = getEffectiveMinFrequency();
1168 double maxf = getEffectiveMaxFrequency(); 1174 double maxf = getEffectiveMaxFrequency();
1169 1175
1170 bool logarithmic = (m_binScale == BinScale::Log); 1176 bool logarithmic = (m_binScale == BinScale::Log);
1171 1177
1178 } 1184 }
1179 1185
1180 bool 1186 bool
1181 SpectrogramLayer::getXBinRange(LayerGeometryProvider *v, int x, double &s0, double &s1) const 1187 SpectrogramLayer::getXBinRange(LayerGeometryProvider *v, int x, double &s0, double &s1) const
1182 { 1188 {
1183 sv_frame_t modelStart = m_model->getStartFrame(); 1189 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1184 sv_frame_t modelEnd = m_model->getEndFrame(); 1190 if (!model) return false;
1191
1192 sv_frame_t modelStart = model->getStartFrame();
1193 sv_frame_t modelEnd = model->getEndFrame();
1185 1194
1186 // Each pixel column covers an exact range of sample frames: 1195 // Each pixel column covers an exact range of sample frames:
1187 sv_frame_t f0 = v->getFrameForX(x) - modelStart; 1196 sv_frame_t f0 = v->getFrameForX(x) - modelStart;
1188 sv_frame_t f1 = v->getFrameForX(x + 1) - modelStart - 1; 1197 sv_frame_t f1 = v->getFrameForX(x + 1) - modelStart - 1;
1189 1198
1202 } 1211 }
1203 1212
1204 bool 1213 bool
1205 SpectrogramLayer::getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &min, RealTime &max) const 1214 SpectrogramLayer::getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &min, RealTime &max) const
1206 { 1215 {
1216 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1217 if (!model) return false;
1218
1207 double s0 = 0, s1 = 0; 1219 double s0 = 0, s1 = 0;
1208 if (!getXBinRange(v, x, s0, s1)) return false; 1220 if (!getXBinRange(v, x, s0, s1)) return false;
1209 1221
1210 int s0i = int(s0 + 0.001); 1222 int s0i = int(s0 + 0.001);
1211 int s1i = int(s1); 1223 int s1i = int(s1);
1213 int windowIncrement = getWindowIncrement(); 1225 int windowIncrement = getWindowIncrement();
1214 int w0 = s0i * windowIncrement - (m_windowSize - windowIncrement)/2; 1226 int w0 = s0i * windowIncrement - (m_windowSize - windowIncrement)/2;
1215 int w1 = s1i * windowIncrement + windowIncrement + 1227 int w1 = s1i * windowIncrement + windowIncrement +
1216 (m_windowSize - windowIncrement)/2 - 1; 1228 (m_windowSize - windowIncrement)/2 - 1;
1217 1229
1218 min = RealTime::frame2RealTime(w0, m_model->getSampleRate()); 1230 min = RealTime::frame2RealTime(w0, model->getSampleRate());
1219 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); 1231 max = RealTime::frame2RealTime(w1, model->getSampleRate());
1220 return true; 1232 return true;
1221 } 1233 }
1222 1234
1223 bool 1235 bool
1224 SpectrogramLayer::getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) 1236 SpectrogramLayer::getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax)
1225 const 1237 const
1226 { 1238 {
1239 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1240 if (!model) return false;
1241
1227 double q0 = 0, q1 = 0; 1242 double q0 = 0, q1 = 0;
1228 if (!getYBinRange(v, y, q0, q1)) return false; 1243 if (!getYBinRange(v, y, q0, q1)) return false;
1229 1244
1230 int q0i = int(q0 + 0.001); 1245 int q0i = int(q0 + 0.001);
1231 int q1i = int(q1); 1246 int q1i = int(q1);
1232 1247
1233 sv_samplerate_t sr = m_model->getSampleRate(); 1248 sv_samplerate_t sr = model->getSampleRate();
1234 1249
1235 for (int q = q0i; q <= q1i; ++q) { 1250 for (int q = q0i; q <= q1i; ++q) {
1236 if (q == q0i) freqMin = (sr * q) / getFFTSize(); 1251 if (q == q0i) freqMin = (sr * q) / getFFTSize();
1237 if (q == q1i) freqMax = (sr * (q+1)) / getFFTSize(); 1252 if (q == q1i) freqMax = (sr * (q+1)) / getFFTSize();
1238 } 1253 }
1243 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, 1258 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y,
1244 double &freqMin, double &freqMax, 1259 double &freqMin, double &freqMax,
1245 double &adjFreqMin, double &adjFreqMax) 1260 double &adjFreqMin, double &adjFreqMax)
1246 const 1261 const
1247 { 1262 {
1248 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1263 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1264 if (!model || !model->isOK() || !model->isReady()) {
1249 return false; 1265 return false;
1250 } 1266 }
1251 1267
1252 FFTModel *fft = getFFTModel(); 1268 auto fft = ModelById::getAs<FFTModel>(m_fftModel);
1253 if (!fft) return false; 1269 if (!fft) return false;
1254 1270
1255 double s0 = 0, s1 = 0; 1271 double s0 = 0, s1 = 0;
1256 if (!getXBinRange(v, x, s0, s1)) return false; 1272 if (!getXBinRange(v, x, s0, s1)) return false;
1257 1273
1262 int s1i = int(s1); 1278 int s1i = int(s1);
1263 1279
1264 int q0i = int(q0 + 0.001); 1280 int q0i = int(q0 + 0.001);
1265 int q1i = int(q1); 1281 int q1i = int(q1);
1266 1282
1267 sv_samplerate_t sr = m_model->getSampleRate(); 1283 sv_samplerate_t sr = model->getSampleRate();
1268 1284
1269 bool haveAdj = false; 1285 bool haveAdj = false;
1270 1286
1271 bool peaksOnly = (m_binDisplay == BinDisplay::PeakBins || 1287 bool peaksOnly = (m_binDisplay == BinDisplay::PeakBins ||
1272 m_binDisplay == BinDisplay::PeakFrequencies); 1288 m_binDisplay == BinDisplay::PeakFrequencies);
1310 bool 1326 bool
1311 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, 1327 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y,
1312 double &min, double &max, 1328 double &min, double &max,
1313 double &phaseMin, double &phaseMax) const 1329 double &phaseMin, double &phaseMax) const
1314 { 1330 {
1315 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1331 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1332 if (!model || !model->isOK() || !model->isReady()) {
1316 return false; 1333 return false;
1317 } 1334 }
1318 1335
1319 double q0 = 0, q1 = 0; 1336 double q0 = 0, q1 = 0;
1320 if (!getYBinRange(v, y, q0, q1)) return false; 1337 if (!getYBinRange(v, y, q0, q1)) return false;
1328 int s0i = int(s0 + 0.001); 1345 int s0i = int(s0 + 0.001);
1329 int s1i = int(s1); 1346 int s1i = int(s1);
1330 1347
1331 bool rv = false; 1348 bool rv = false;
1332 1349
1333 FFTModel *fft = getFFTModel(); 1350 auto fft = ModelById::getAs<FFTModel>(m_fftModel);
1334 1351
1335 if (fft) { 1352 if (fft) {
1336 1353
1337 int cw = fft->getWidth(); 1354 int cw = fft->getWidth();
1338 int ch = fft->getHeight(); 1355 int ch = fft->getHeight();
1373 void 1390 void
1374 SpectrogramLayer::recreateFFTModel() 1391 SpectrogramLayer::recreateFFTModel()
1375 { 1392 {
1376 SVDEBUG << "SpectrogramLayer::recreateFFTModel called" << endl; 1393 SVDEBUG << "SpectrogramLayer::recreateFFTModel called" << endl;
1377 1394
1378 if (!m_model || !m_model->isOK()) { 1395 { // scope, avoid hanging on to this pointer
1379 emit sliceableModelReplaced(m_fftModel, nullptr); 1396 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1380 deleteDerivedModels(); 1397 if (!model || !model->isOK()) {
1381 return; 1398 deleteDerivedModels();
1382 } 1399 return;
1383 1400 }
1384 if (m_fftModel) m_fftModel->aboutToDelete(); 1401 }
1385 1402
1386 if (m_peakCache) m_peakCache->aboutToDelete(); 1403 deleteDerivedModels();
1387 delete m_peakCache; 1404
1388 m_peakCache = nullptr; 1405 auto newFFTModel = std::make_shared<FFTModel>(m_model,
1389 1406 m_channel,
1390 if (m_wholeCache) m_wholeCache->aboutToDelete(); 1407 m_windowType,
1391 delete m_wholeCache; 1408 m_windowSize,
1392 m_wholeCache = nullptr; 1409 getWindowIncrement(),
1393 1410 getFFTSize());
1394 FFTModel *newModel = new FFTModel(m_model, 1411
1395 m_channel, 1412 if (!newFFTModel->isOK()) {
1396 m_windowType,
1397 m_windowSize,
1398 getWindowIncrement(),
1399 getFFTSize());
1400
1401 if (!newModel->isOK()) {
1402 QMessageBox::critical 1413 QMessageBox::critical
1403 (nullptr, tr("FFT cache failed"), 1414 (nullptr, tr("FFT cache failed"),
1404 tr("Failed to create the FFT model for this spectrogram.\n" 1415 tr("Failed to create the FFT model for this spectrogram.\n"
1405 "There may be insufficient memory or disc space to continue.")); 1416 "There may be insufficient memory or disc space to continue."));
1406 delete newModel;
1407 delete m_fftModel;
1408 m_fftModel = nullptr;
1409 return; 1417 return;
1410 } 1418 }
1411 1419
1412 FFTModel *oldModel = m_fftModel; 1420 ModelById::add(newFFTModel);
1413 m_fftModel = newModel; 1421 m_fftModel = newFFTModel->getId();
1414 1422
1415 bool createWholeCache = false; 1423 bool createWholeCache = false;
1416 checkCacheSpace(&m_peakCacheDivisor, &createWholeCache); 1424 checkCacheSpace(&m_peakCacheDivisor, &createWholeCache);
1417 1425
1418 if (createWholeCache) { 1426 if (createWholeCache) {
1419 m_wholeCache = new Dense3DModelPeakCache(m_fftModel, 1); 1427
1420 m_peakCache = new Dense3DModelPeakCache(m_wholeCache, m_peakCacheDivisor); 1428 auto whole = std::make_shared<Dense3DModelPeakCache>(m_fftModel, 1);
1429 ModelById::add(whole);
1430 m_wholeCache = whole->getId();
1431
1432 auto peaks = std::make_shared<Dense3DModelPeakCache>(m_wholeCache,
1433 m_peakCacheDivisor);
1434 ModelById::add(peaks);
1435 m_peakCache = peaks->getId();
1436
1421 } else { 1437 } else {
1422 m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor); 1438
1423 } 1439 auto peaks = std::make_shared<Dense3DModelPeakCache>(m_fftModel,
1424 1440 m_peakCacheDivisor);
1425 emit sliceableModelReplaced(oldModel, m_fftModel); 1441 ModelById::add(peaks);
1426 delete oldModel; 1442 m_peakCache = peaks->getId();
1443 }
1427 } 1444 }
1428 1445
1429 void 1446 void
1430 SpectrogramLayer::checkCacheSpace(int *suggestedPeakDivisor, 1447 SpectrogramLayer::checkCacheSpace(int *suggestedPeakDivisor,
1431 bool *createWholeCache) const 1448 bool *createWholeCache) const
1432 { 1449 {
1433 *suggestedPeakDivisor = 8; 1450 *suggestedPeakDivisor = 8;
1434 *createWholeCache = false; 1451 *createWholeCache = false;
1435 1452
1436 if (!m_fftModel) return; 1453 auto fftModel = ModelById::getAs<FFTModel>(m_fftModel);
1454 if (!fftModel) return;
1437 1455
1438 size_t sz = 1456 size_t sz =
1439 size_t(m_fftModel->getWidth()) * 1457 size_t(fftModel->getWidth()) *
1440 size_t(m_fftModel->getHeight()) * 1458 size_t(fftModel->getHeight()) *
1441 sizeof(float); 1459 sizeof(float);
1442 1460
1443 try { 1461 try {
1444 SVDEBUG << "Requesting advice from StorageAdviser on whether to create whole-model cache" << endl; 1462 SVDEBUG << "Requesting advice from StorageAdviser on whether to create whole-model cache" << endl;
1445 // The lower amount here is the amount required for the 1463 // The lower amount here is the amount required for the
1465 } catch (const InsufficientDiscSpace &) { 1483 } catch (const InsufficientDiscSpace &) {
1466 SVDEBUG << "Seems like a terrible idea to create whole-model cache" << endl; 1484 SVDEBUG << "Seems like a terrible idea to create whole-model cache" << endl;
1467 } 1485 }
1468 } 1486 }
1469 1487
1470 const Model * 1488 ModelId
1471 SpectrogramLayer::getSliceableModel() const 1489 SpectrogramLayer::getSliceableModel() const
1472 { 1490 {
1473 return m_fftModel; 1491 return m_fftModel;
1474 } 1492 }
1475 1493
1495 1513
1496 if (m_renderers.find(viewId) == m_renderers.end()) { 1514 if (m_renderers.find(viewId) == m_renderers.end()) {
1497 1515
1498 Colour3DPlotRenderer::Sources sources; 1516 Colour3DPlotRenderer::Sources sources;
1499 sources.verticalBinLayer = this; 1517 sources.verticalBinLayer = this;
1500 sources.fft = getFFTModel(); 1518 sources.fft = m_fftModel;
1501 sources.source = sources.fft; 1519 sources.source = sources.fft;
1502 if (m_peakCache) sources.peakCaches.push_back(m_peakCache); 1520 if (!m_peakCache.isNone()) sources.peakCaches.push_back(m_peakCache);
1503 if (m_wholeCache) sources.peakCaches.push_back(m_wholeCache); 1521 if (!m_wholeCache.isNone()) sources.peakCaches.push_back(m_wholeCache);
1504 1522
1505 ColourScale::Parameters cparams; 1523 ColourScale::Parameters cparams;
1506 cparams.colourMap = m_colourMap; 1524 cparams.colourMap = m_colourMap;
1507 cparams.scaleType = m_colourScale; 1525 cparams.scaleType = m_colourScale;
1508 cparams.multiple = m_colourScaleMultiple; 1526 cparams.multiple = m_colourScaleMultiple;
1634 cerr << "SpectrogramLayer::paint() entering: m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl; 1652 cerr << "SpectrogramLayer::paint() entering: m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl;
1635 1653
1636 cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; 1654 cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl;
1637 #endif 1655 #endif
1638 1656
1639 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1657 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1658 if (!model || !model->isOK() || !model->isReady()) {
1640 return; 1659 return;
1641 } 1660 }
1642 1661
1643 paintWithRenderer(v, paint, rect); 1662 paintWithRenderer(v, paint, rect);
1644 1663
1648 void 1667 void
1649 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const 1668 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const
1650 { 1669 {
1651 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); 1670 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures");
1652 1671
1672 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1673
1653 QPoint localPos; 1674 QPoint localPos;
1654 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { 1675 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !model) {
1655 return; 1676 return;
1656 } 1677 }
1657 1678
1658 #ifdef DEBUG_SPECTROGRAM_REPAINT 1679 #ifdef DEBUG_SPECTROGRAM_REPAINT
1659 cerr << "SpectrogramLayer: illuminateLocalFeatures(" 1680 cerr << "SpectrogramLayer: illuminateLocalFeatures("
1707 } 1728 }
1708 1729
1709 int 1730 int
1710 SpectrogramLayer::getCompletion(LayerGeometryProvider *) const 1731 SpectrogramLayer::getCompletion(LayerGeometryProvider *) const
1711 { 1732 {
1712 if (!m_fftModel) return 100; 1733 auto fftModel = ModelById::getAs<FFTModel>(m_fftModel);
1713 int completion = m_fftModel->getCompletion(); 1734 if (!fftModel) return 100;
1735 int completion = fftModel->getCompletion();
1714 #ifdef DEBUG_SPECTROGRAM_REPAINT 1736 #ifdef DEBUG_SPECTROGRAM_REPAINT
1715 cerr << "SpectrogramLayer::getCompletion: completion = " << completion << endl; 1737 cerr << "SpectrogramLayer::getCompletion: completion = " << completion << endl;
1716 #endif 1738 #endif
1717 return completion; 1739 return completion;
1718 } 1740 }
1719 1741
1720 QString 1742 QString
1721 SpectrogramLayer::getError(LayerGeometryProvider *) const 1743 SpectrogramLayer::getError(LayerGeometryProvider *) const
1722 { 1744 {
1723 if (!m_fftModel) return ""; 1745 auto fftModel = ModelById::getAs<FFTModel>(m_fftModel);
1724 return m_fftModel->getError(); 1746 if (!fftModel) return "";
1747 return fftModel->getError();
1725 } 1748 }
1726 1749
1727 bool 1750 bool
1728 SpectrogramLayer::getValueExtents(double &min, double &max, 1751 SpectrogramLayer::getValueExtents(double &min, double &max,
1729 bool &logarithmic, QString &unit) const 1752 bool &logarithmic, QString &unit) const
1730 { 1753 {
1731 if (!m_model) return false; 1754 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1732 1755 if (!model) return false;
1733 sv_samplerate_t sr = m_model->getSampleRate(); 1756
1757 sv_samplerate_t sr = model->getSampleRate();
1734 min = double(sr) / getFFTSize(); 1758 min = double(sr) / getFFTSize();
1735 max = double(sr) / 2; 1759 max = double(sr) / 2;
1736 1760
1737 logarithmic = (m_binScale == BinScale::Log); 1761 logarithmic = (m_binScale == BinScale::Log);
1738 unit = "Hz"; 1762 unit = "Hz";
1750 } 1774 }
1751 1775
1752 bool 1776 bool
1753 SpectrogramLayer::setDisplayExtents(double min, double max) 1777 SpectrogramLayer::setDisplayExtents(double min, double max)
1754 { 1778 {
1755 if (!m_model) return false; 1779 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1780 if (!model) return false;
1756 1781
1757 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl; 1782 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl;
1758 1783
1759 if (min < 0) min = 0; 1784 if (min < 0) min = 0;
1760 if (max > m_model->getSampleRate()/2.0) max = m_model->getSampleRate()/2.0; 1785 if (max > model->getSampleRate()/2.0) max = model->getSampleRate()/2.0;
1761 1786
1762 int minf = int(lrint(min)); 1787 int minf = int(lrint(min));
1763 int maxf = int(lrint(max)); 1788 int maxf = int(lrint(max));
1764 1789
1765 if (m_minFrequency == minf && m_maxFrequency == maxf) return true; 1790 if (m_minFrequency == minf && m_maxFrequency == maxf) return true;
1830 bool 1855 bool
1831 SpectrogramLayer::getCrosshairExtents(LayerGeometryProvider *v, QPainter &paint, 1856 SpectrogramLayer::getCrosshairExtents(LayerGeometryProvider *v, QPainter &paint,
1832 QPoint cursorPos, 1857 QPoint cursorPos,
1833 vector<QRect> &extents) const 1858 vector<QRect> &extents) const
1834 { 1859 {
1860 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested
1861 // replacement (horizontalAdvance) was only added in Qt 5.11
1862 // which is too new for us
1863 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1864
1835 QRect vertical(cursorPos.x() - 12, 0, 12, v->getPaintHeight()); 1865 QRect vertical(cursorPos.x() - 12, 0, 12, v->getPaintHeight());
1836 extents.push_back(vertical); 1866 extents.push_back(vertical);
1837 1867
1838 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1); 1868 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1);
1839 extents.push_back(horizontal); 1869 extents.push_back(horizontal);
1868 1898
1869 void 1899 void
1870 SpectrogramLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, 1900 SpectrogramLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint,
1871 QPoint cursorPos) const 1901 QPoint cursorPos) const
1872 { 1902 {
1903 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1904 if (!model) return;
1905
1873 paint.save(); 1906 paint.save();
1874 1907
1875 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint); 1908 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint);
1876 1909
1877 QFont fn = paint.font(); 1910 QFont fn = paint.font();
1884 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); 1917 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y());
1885 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->getPaintHeight()); 1918 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->getPaintHeight());
1886 1919
1887 double fundamental = getFrequencyForY(v, cursorPos.y()); 1920 double fundamental = getFrequencyForY(v, cursorPos.y());
1888 1921
1889 PaintAssistant::drawVisibleText(v, paint, 1922 PaintAssistant::drawVisibleText
1890 sw + 2, 1923 (v, paint,
1891 cursorPos.y() - 2, 1924 sw + 2,
1892 QString("%1 Hz").arg(fundamental), 1925 cursorPos.y() - 2,
1893 PaintAssistant::OutlinedText); 1926 QString("%1 Hz").arg(fundamental),
1927 PaintAssistant::OutlinedText);
1894 1928
1895 if (Pitch::isFrequencyInMidiRange(fundamental)) { 1929 if (Pitch::isFrequencyInMidiRange(fundamental)) {
1896 QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental); 1930 QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental);
1897 PaintAssistant::drawVisibleText(v, paint, 1931 PaintAssistant::drawVisibleText
1898 sw + 2, 1932 (v, paint,
1899 cursorPos.y() + paint.fontMetrics().ascent() + 2, 1933 sw + 2,
1900 pitchLabel, 1934 cursorPos.y() + paint.fontMetrics().ascent() + 2,
1901 PaintAssistant::OutlinedText); 1935 pitchLabel,
1936 PaintAssistant::OutlinedText);
1902 } 1937 }
1903 1938
1904 sv_frame_t frame = v->getFrameForX(cursorPos.x()); 1939 sv_frame_t frame = v->getFrameForX(cursorPos.x());
1905 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); 1940 RealTime rt = RealTime::frame2RealTime(frame, model->getSampleRate());
1906 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); 1941 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str());
1907 QString frameLabel = QString("%1").arg(frame); 1942 QString frameLabel = QString("%1").arg(frame);
1908 PaintAssistant::drawVisibleText(v, paint, 1943 PaintAssistant::drawVisibleText
1909 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, 1944 (v, paint,
1910 v->getPaintHeight() - 2, 1945 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2,
1911 frameLabel, 1946 v->getPaintHeight() - 2,
1912 PaintAssistant::OutlinedText); 1947 frameLabel,
1913 PaintAssistant::drawVisibleText(v, paint, 1948 PaintAssistant::OutlinedText);
1914 cursorPos.x() + 2, 1949 PaintAssistant::drawVisibleText
1915 v->getPaintHeight() - 2, 1950 (v, paint,
1916 rtLabel, 1951 cursorPos.x() + 2,
1917 PaintAssistant::OutlinedText); 1952 v->getPaintHeight() - 2,
1953 rtLabel,
1954 PaintAssistant::OutlinedText);
1918 1955
1919 int harmonic = 2; 1956 int harmonic = 2;
1920 1957
1921 while (harmonic < 100) { 1958 while (harmonic < 100) {
1922 1959
1948 SpectrogramLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 1985 SpectrogramLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
1949 { 1986 {
1950 int x = pos.x(); 1987 int x = pos.x();
1951 int y = pos.y(); 1988 int y = pos.y();
1952 1989
1953 if (!m_model || !m_model->isOK()) return ""; 1990 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
1991 if (!model || !model->isOK()) return "";
1954 1992
1955 double magMin = 0, magMax = 0; 1993 double magMin = 0, magMax = 0;
1956 double phaseMin = 0, phaseMax = 0; 1994 double phaseMin = 0, phaseMax = 0;
1957 double freqMin = 0, freqMax = 0; 1995 double freqMin = 0, freqMax = 0;
1958 double adjFreqMin = 0, adjFreqMax = 0; 1996 double adjFreqMin = 0, adjFreqMax = 0;
2067 } 2105 }
2068 2106
2069 int 2107 int
2070 SpectrogramLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool detailed, QPainter &paint) const 2108 SpectrogramLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool detailed, QPainter &paint) const
2071 { 2109 {
2072 if (!m_model || !m_model->isOK()) return 0; 2110 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2111 if (!model || !model->isOK()) return 0;
2073 2112
2074 int cw = 0; 2113 int cw = 0;
2075 if (detailed) cw = getColourScaleWidth(paint); 2114 if (detailed) cw = getColourScaleWidth(paint);
2076 2115
2077 int tw = paint.fontMetrics().width(QString("%1") 2116 int tw = paint.fontMetrics().width(QString("%1")
2078 .arg(m_maxFrequency > 0 ? 2117 .arg(m_maxFrequency > 0 ?
2079 m_maxFrequency - 1 : 2118 m_maxFrequency - 1 :
2080 m_model->getSampleRate() / 2)); 2119 model->getSampleRate() / 2));
2081 2120
2082 int fw = paint.fontMetrics().width(tr("43Hz")); 2121 int fw = paint.fontMetrics().width(tr("43Hz"));
2083 if (tw < fw) tw = fw; 2122 if (tw < fw) tw = fw;
2084 2123
2085 int tickw = (m_binScale == BinScale::Log ? 10 : 4); 2124 int tickw = (m_binScale == BinScale::Log ? 10 : 4);
2089 2128
2090 void 2129 void
2091 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, 2130 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed,
2092 QPainter &paint, QRect rect) const 2131 QPainter &paint, QRect rect) const
2093 { 2132 {
2094 if (!m_model || !m_model->isOK()) { 2133 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2134 if (!model || !model->isOK()) {
2095 return; 2135 return;
2096 } 2136 }
2097 2137
2098 Profiler profiler("SpectrogramLayer::paintVerticalScale"); 2138 Profiler profiler("SpectrogramLayer::paintVerticalScale");
2099 2139
2109 2149
2110 int tickw = (m_binScale == BinScale::Log ? 10 : 4); 2150 int tickw = (m_binScale == BinScale::Log ? 10 : 4);
2111 int pkw = (m_binScale == BinScale::Log ? 10 : 0); 2151 int pkw = (m_binScale == BinScale::Log ? 10 : 0);
2112 2152
2113 int bins = getFFTSize() / 2; 2153 int bins = getFFTSize() / 2;
2114 sv_samplerate_t sr = m_model->getSampleRate(); 2154 sv_samplerate_t sr = model->getSampleRate();
2115 2155
2116 if (m_maxFrequency > 0) { 2156 if (m_maxFrequency > 0) {
2117 bins = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); 2157 bins = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1);
2118 if (bins > getFFTSize() / 2) bins = getFFTSize() / 2; 2158 if (bins > getFFTSize() / 2) bins = getFFTSize() / 2;
2119 } 2159 }
2379 }; 2419 };
2380 2420
2381 int 2421 int
2382 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const 2422 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const
2383 { 2423 {
2384 if (!m_model) return 0; 2424 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2385 2425 if (!model) return 0;
2386 sv_samplerate_t sr = m_model->getSampleRate(); 2426
2427 sv_samplerate_t sr = model->getSampleRate();
2387 2428
2388 SpectrogramRangeMapper mapper(sr, getFFTSize()); 2429 SpectrogramRangeMapper mapper(sr, getFFTSize());
2389 2430
2390 // int maxStep = mapper.getPositionForValue((double(sr) / getFFTSize()) + 0.001); 2431 // int maxStep = mapper.getPositionForValue((double(sr) / getFFTSize()) + 0.001);
2391 int maxStep = mapper.getPositionForValue(0); 2432 int maxStep = mapper.getPositionForValue(0);
2402 } 2443 }
2403 2444
2404 int 2445 int
2405 SpectrogramLayer::getCurrentVerticalZoomStep() const 2446 SpectrogramLayer::getCurrentVerticalZoomStep() const
2406 { 2447 {
2407 if (!m_model) return 0; 2448 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2449 if (!model) return 0;
2408 2450
2409 double dmin, dmax; 2451 double dmin, dmax;
2410 getDisplayExtents(dmin, dmax); 2452 getDisplayExtents(dmin, dmax);
2411 2453
2412 SpectrogramRangeMapper mapper(m_model->getSampleRate(), getFFTSize()); 2454 SpectrogramRangeMapper mapper(model->getSampleRate(), getFFTSize());
2413 int n = mapper.getPositionForValue(dmax - dmin); 2455 int n = mapper.getPositionForValue(dmax - dmin);
2414 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl; 2456 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl;
2415 return n; 2457 return n;
2416 } 2458 }
2417 2459
2418 void 2460 void
2419 SpectrogramLayer::setVerticalZoomStep(int step) 2461 SpectrogramLayer::setVerticalZoomStep(int step)
2420 { 2462 {
2421 if (!m_model) return; 2463 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2464 if (!model) return;
2422 2465
2423 double dmin = m_minFrequency, dmax = m_maxFrequency; 2466 double dmin = m_minFrequency, dmax = m_maxFrequency;
2424 // getDisplayExtents(dmin, dmax); 2467 // getDisplayExtents(dmin, dmax);
2425 2468
2426 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl; 2469 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl;
2427 2470
2428 sv_samplerate_t sr = m_model->getSampleRate(); 2471 sv_samplerate_t sr = model->getSampleRate();
2429 SpectrogramRangeMapper mapper(sr, getFFTSize()); 2472 SpectrogramRangeMapper mapper(sr, getFFTSize());
2430 double newdist = mapper.getValueForPosition(step); 2473 double newdist = mapper.getValueForPosition(step);
2431 2474
2432 double newmin, newmax; 2475 double newmin, newmax;
2433 2476
2484 } 2527 }
2485 2528
2486 RangeMapper * 2529 RangeMapper *
2487 SpectrogramLayer::getNewVerticalZoomRangeMapper() const 2530 SpectrogramLayer::getNewVerticalZoomRangeMapper() const
2488 { 2531 {
2489 if (!m_model) return nullptr; 2532 auto model = ModelById::getAs<DenseTimeValueModel>(m_model);
2490 return new SpectrogramRangeMapper(m_model->getSampleRate(), getFFTSize()); 2533 if (!model) return nullptr;
2534 return new SpectrogramRangeMapper(model->getSampleRate(), getFFTSize());
2491 } 2535 }
2492 2536
2493 void 2537 void
2494 SpectrogramLayer::updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const 2538 SpectrogramLayer::updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const
2495 { 2539 {