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