comparison layer/SpectrogramLayer.cpp @ 918:4fe7a09be0fe osx-retina

Many fixes for the previous stuff
author Chris Cannam
date Tue, 17 Mar 2015 16:56:03 +0000
parents 94e4952a6774
children e39d5d2734ed
comparison
equal deleted inserted replaced
917:77a1d42353ce 918:4fe7a09be0fe
576 { 576 {
577 for (ViewImageCache::iterator i = m_imageCaches.begin(); 577 for (ViewImageCache::iterator i = m_imageCaches.begin();
578 i != m_imageCaches.end(); ++i) { 578 i != m_imageCaches.end(); ++i) {
579 579
580 //!!! when are views removed from the map? on setLayerDormant? 580 //!!! when are views removed from the map? on setLayerDormant?
581 const View *v = i->first; 581 const LayerGeometryProvider *v = i->first;
582 582
583 #ifdef DEBUG_SPECTROGRAM_REPAINT 583 #ifdef DEBUG_SPECTROGRAM_REPAINT
584 SVDEBUG << "SpectrogramLayer::invalidateImageCaches(" 584 SVDEBUG << "SpectrogramLayer::invalidateImageCaches("
585 << startFrame << ", " << endFrame << "): view range is " 585 << startFrame << ", " << endFrame << "): view range is "
586 << v->getStartFrame() << ", " << v->getEndFrame() 586 << v->getStartFrame() << ", " << v->getEndFrame()
603 #ifdef DEBUG_SPECTROGRAM_REPAINT 603 #ifdef DEBUG_SPECTROGRAM_REPAINT
604 SVDEBUG << "clipping from 0 to " << x-1 << endl; 604 SVDEBUG << "clipping from 0 to " << x-1 << endl;
605 #endif 605 #endif
606 if (x > 1) { 606 if (x > 1) {
607 i->second.validArea &= 607 i->second.validArea &=
608 QRect(0, 0, x-1, v->height()); 608 QRect(0, 0, x-1, v->getPaintHeight());
609 } else { 609 } else {
610 i->second.validArea = QRect(); 610 i->second.validArea = QRect();
611 } 611 }
612 } else { 612 } else {
613 if (int(endFrame) < v->getStartFrame()) { 613 if (int(endFrame) < v->getStartFrame()) {
616 #endif 616 #endif
617 return; 617 return;
618 } 618 }
619 int x = v->getXForFrame(endFrame); 619 int x = v->getXForFrame(endFrame);
620 #ifdef DEBUG_SPECTROGRAM_REPAINT 620 #ifdef DEBUG_SPECTROGRAM_REPAINT
621 SVDEBUG << "clipping from " << x+1 << " to " << v->width() 621 SVDEBUG << "clipping from " << x+1 << " to " << v->getPaintWidth()
622 << endl; 622 << endl;
623 #endif 623 #endif
624 if (x < v->width()) { 624 if (x < v->getPaintWidth()) {
625 i->second.validArea &= 625 i->second.validArea &=
626 QRect(x+1, 0, v->width()-(x+1), v->height()); 626 QRect(x+1, 0, v->getPaintWidth()-(x+1), v->getPaintHeight());
627 } else { 627 } else {
628 i->second.validArea = QRect(); 628 i->second.validArea = QRect();
629 } 629 }
630 } 630 }
631 631
989 { 989 {
990 return m_normalizeVisibleArea; 990 return m_normalizeVisibleArea;
991 } 991 }
992 992
993 void 993 void
994 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) 994 SpectrogramLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant)
995 { 995 {
996 if (dormant) { 996 if (dormant) {
997 997
998 #ifdef DEBUG_SPECTROGRAM_REPAINT 998 #ifdef DEBUG_SPECTROGRAM_REPAINT
999 SVDEBUG << "SpectrogramLayer::setLayerDormant(" << dormant << ")" 999 SVDEBUG << "SpectrogramLayer::setLayerDormant(" << dormant << ")"
1179 1179
1180 m_drawBuffer = QImage(); 1180 m_drawBuffer = QImage();
1181 } 1181 }
1182 1182
1183 unsigned char 1183 unsigned char
1184 SpectrogramLayer::getDisplayValue(View *v, double input) const 1184 SpectrogramLayer::getDisplayValue(LayerGeometryProvider *v, double input) const
1185 { 1185 {
1186 int value; 1186 int value;
1187 1187
1188 double min = 0.0; 1188 double min = 0.0;
1189 double max = 1.0; 1189 double max = 1.0;
1292 1292
1293 return maxf; 1293 return maxf;
1294 } 1294 }
1295 1295
1296 bool 1296 bool
1297 SpectrogramLayer::getYBinRange(View *v, int y, double &q0, double &q1) const 1297 SpectrogramLayer::getYBinRange(LayerGeometryProvider *v, int y, double &q0, double &q1) const
1298 { 1298 {
1299 Profiler profiler("SpectrogramLayer::getYBinRange"); 1299 Profiler profiler("SpectrogramLayer::getYBinRange");
1300 1300
1301 int h = v->height(); 1301 int h = v->getPaintHeight();
1302 if (y < 0 || y >= h) return false; 1302 if (y < 0 || y >= h) return false;
1303 1303
1304 sv_samplerate_t sr = m_model->getSampleRate(); 1304 sv_samplerate_t sr = m_model->getSampleRate();
1305 double minf = getEffectiveMinFrequency(); 1305 double minf = getEffectiveMinFrequency();
1306 double maxf = getEffectiveMaxFrequency(); 1306 double maxf = getEffectiveMaxFrequency();
1318 1318
1319 return true; 1319 return true;
1320 } 1320 }
1321 1321
1322 bool 1322 bool
1323 SpectrogramLayer::getSmoothedYBinRange(View *v, int y, double &q0, double &q1) const 1323 SpectrogramLayer::getSmoothedYBinRange(LayerGeometryProvider *v, int y, double &q0, double &q1) const
1324 { 1324 {
1325 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange"); 1325 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange");
1326 1326
1327 int h = v->height(); 1327 int h = v->getPaintHeight();
1328 if (y < 0 || y >= h) return false; 1328 if (y < 0 || y >= h) return false;
1329 1329
1330 sv_samplerate_t sr = m_model->getSampleRate(); 1330 sv_samplerate_t sr = m_model->getSampleRate();
1331 double minf = getEffectiveMinFrequency(); 1331 double minf = getEffectiveMinFrequency();
1332 double maxf = getEffectiveMaxFrequency(); 1332 double maxf = getEffectiveMaxFrequency();
1344 1344
1345 return true; 1345 return true;
1346 } 1346 }
1347 1347
1348 bool 1348 bool
1349 SpectrogramLayer::getXBinRange(View *v, int x, double &s0, double &s1) const 1349 SpectrogramLayer::getXBinRange(LayerGeometryProvider *v, int x, double &s0, double &s1) const
1350 { 1350 {
1351 sv_frame_t modelStart = m_model->getStartFrame(); 1351 sv_frame_t modelStart = m_model->getStartFrame();
1352 sv_frame_t modelEnd = m_model->getEndFrame(); 1352 sv_frame_t modelEnd = m_model->getEndFrame();
1353 1353
1354 // Each pixel column covers an exact range of sample frames: 1354 // Each pixel column covers an exact range of sample frames:
1368 1368
1369 return true; 1369 return true;
1370 } 1370 }
1371 1371
1372 bool 1372 bool
1373 SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const 1373 SpectrogramLayer::getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &min, RealTime &max) const
1374 { 1374 {
1375 double s0 = 0, s1 = 0; 1375 double s0 = 0, s1 = 0;
1376 if (!getXBinRange(v, x, s0, s1)) return false; 1376 if (!getXBinRange(v, x, s0, s1)) return false;
1377 1377
1378 int s0i = int(s0 + 0.001); 1378 int s0i = int(s0 + 0.001);
1387 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); 1387 max = RealTime::frame2RealTime(w1, m_model->getSampleRate());
1388 return true; 1388 return true;
1389 } 1389 }
1390 1390
1391 bool 1391 bool
1392 SpectrogramLayer::getYBinSourceRange(View *v, int y, double &freqMin, double &freqMax) 1392 SpectrogramLayer::getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax)
1393 const 1393 const
1394 { 1394 {
1395 double q0 = 0, q1 = 0; 1395 double q0 = 0, q1 = 0;
1396 if (!getYBinRange(v, y, q0, q1)) return false; 1396 if (!getYBinRange(v, y, q0, q1)) return false;
1397 1397
1406 } 1406 }
1407 return true; 1407 return true;
1408 } 1408 }
1409 1409
1410 bool 1410 bool
1411 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, 1411 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y,
1412 double &freqMin, double &freqMax, 1412 double &freqMin, double &freqMax,
1413 double &adjFreqMin, double &adjFreqMax) 1413 double &adjFreqMin, double &adjFreqMax)
1414 const 1414 const
1415 { 1415 {
1416 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1416 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1473 1473
1474 return haveAdj; 1474 return haveAdj;
1475 } 1475 }
1476 1476
1477 bool 1477 bool
1478 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y, 1478 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y,
1479 double &min, double &max, 1479 double &min, double &max,
1480 double &phaseMin, double &phaseMax) const 1480 double &phaseMin, double &phaseMax) const
1481 { 1481 {
1482 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1482 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1483 return false; 1483 return false;
1542 1542
1543 return rv; 1543 return rv;
1544 } 1544 }
1545 1545
1546 int 1546 int
1547 SpectrogramLayer::getZeroPadLevel(const View *v) const 1547 SpectrogramLayer::getZeroPadLevel(const LayerGeometryProvider *v) const
1548 { 1548 {
1549 //!!! tidy all this stuff 1549 //!!! tidy all this stuff
1550 1550
1551 if (m_binDisplay != AllBins) return 0; 1551 if (m_binDisplay != AllBins) return 0;
1552 1552
1572 if (minbin < 1) minbin = 1; 1572 if (minbin < 1) minbin = 1;
1573 if (minbin >= maxbin) minbin = maxbin - 1; 1573 if (minbin >= maxbin) minbin = maxbin - 1;
1574 } 1574 }
1575 1575
1576 double perPixel = 1576 double perPixel =
1577 double(v->height()) / 1577 double(v->getPaintHeight()) /
1578 double((maxbin - minbin) / (m_zeroPadLevel + 1)); 1578 double((maxbin - minbin) / (m_zeroPadLevel + 1));
1579 1579
1580 if (perPixel > 2.8) { 1580 if (perPixel > 2.8) {
1581 return 3; // 4x oversampling 1581 return 3; // 4x oversampling
1582 } else if (perPixel > 1.5) { 1582 } else if (perPixel > 1.5) {
1585 return 0; // 1x 1585 return 0; // 1x
1586 } 1586 }
1587 } 1587 }
1588 1588
1589 int 1589 int
1590 SpectrogramLayer::getFFTSize(const View *v) const 1590 SpectrogramLayer::getFFTSize(const LayerGeometryProvider *v) const
1591 { 1591 {
1592 return m_fftSize * (getZeroPadLevel(v) + 1); 1592 return m_fftSize * (getZeroPadLevel(v) + 1);
1593 } 1593 }
1594 1594
1595 FFTModel * 1595 FFTModel *
1596 SpectrogramLayer::getFFTModel(const View *v) const 1596 SpectrogramLayer::getFFTModel(const LayerGeometryProvider *v) const
1597 { 1597 {
1598 if (!m_model) return 0; 1598 if (!m_model) return 0;
1599 1599
1600 int fftSize = getFFTSize(v); 1600 int fftSize = getFFTSize(v);
1601 1601
1665 1665
1666 return m_fftModels[v].first; 1666 return m_fftModels[v].first;
1667 } 1667 }
1668 1668
1669 Dense3DModelPeakCache * 1669 Dense3DModelPeakCache *
1670 SpectrogramLayer::getPeakCache(const View *v) const 1670 SpectrogramLayer::getPeakCache(const LayerGeometryProvider *v) const
1671 { 1671 {
1672 if (!m_peakCaches[v]) { 1672 if (!m_peakCaches[v]) {
1673 FFTModel *f = getFFTModel(v); 1673 FFTModel *f = getFFTModel(v);
1674 if (!f) return 0; 1674 if (!f) return 0;
1675 m_peakCaches[v] = new Dense3DModelPeakCache(f, 8); 1675 m_peakCaches[v] = new Dense3DModelPeakCache(f, 8);
1717 *i = MagnitudeRange(); 1717 *i = MagnitudeRange();
1718 } 1718 }
1719 } 1719 }
1720 1720
1721 bool 1721 bool
1722 SpectrogramLayer::updateViewMagnitudes(View *v) const 1722 SpectrogramLayer::updateViewMagnitudes(LayerGeometryProvider *v) const
1723 { 1723 {
1724 MagnitudeRange mag; 1724 MagnitudeRange mag;
1725 1725
1726 int x0 = 0, x1 = v->width(); 1726 int x0 = 0, x1 = v->getPaintWidth();
1727 double s00 = 0, s01 = 0, s10 = 0, s11 = 0; 1727 double s00 = 0, s01 = 0, s10 = 0, s11 = 0;
1728 1728
1729 if (!getXBinRange(v, x0, s00, s01)) { 1729 if (!getXBinRange(v, x0, s00, s01)) {
1730 s00 = s01 = double(m_model->getStartFrame()) / getWindowIncrement(); 1730 s00 = s01 = double(m_model->getStartFrame()) / getWindowIncrement();
1731 } 1731 }
1821 #endif 1821 #endif
1822 1822
1823 int zoomLevel = v->getZoomLevel(); 1823 int zoomLevel = v->getZoomLevel();
1824 1824
1825 int x0 = 0; 1825 int x0 = 0;
1826 int x1 = v->width(); 1826 int x1 = v->getPaintWidth();
1827 1827
1828 bool recreateWholeImageCache = true; 1828 bool recreateWholeImageCache = true;
1829 1829
1830 x0 = rect.left(); 1830 x0 = rect.left();
1831 x1 = rect.right() + 1; 1831 x1 = rect.right() + 1;
1838 1838
1839 int cw = cache.image.width(); 1839 int cw = cache.image.width();
1840 int ch = cache.image.height(); 1840 int ch = cache.image.height();
1841 1841
1842 if (int(cache.zoomLevel) == zoomLevel && 1842 if (int(cache.zoomLevel) == zoomLevel &&
1843 cw == v->width() && 1843 cw == v->getPaintWidth() &&
1844 ch == v->height()) { 1844 ch == v->getPaintHeight()) {
1845 1845
1846 if (v->getXForFrame(cache.startFrame) == 1846 if (v->getXForFrame(cache.startFrame) ==
1847 v->getXForFrame(startFrame) && 1847 v->getXForFrame(startFrame) &&
1848 cache.validArea.x() <= x0 && 1848 cache.validArea.x() <= x0 &&
1849 cache.validArea.x() + cache.validArea.width() >= x1) { 1849 cache.validArea.x() + cache.validArea.width() >= x1) {
1945 cerr << "SpectrogramLayer: image cache useless" << endl; 1945 cerr << "SpectrogramLayer: image cache useless" << endl;
1946 if (int(cache.zoomLevel) != zoomLevel) { 1946 if (int(cache.zoomLevel) != zoomLevel) {
1947 cerr << "(cache zoomLevel " << cache.zoomLevel 1947 cerr << "(cache zoomLevel " << cache.zoomLevel
1948 << " != " << zoomLevel << ")" << endl; 1948 << " != " << zoomLevel << ")" << endl;
1949 } 1949 }
1950 if (cw != v->width()) { 1950 if (cw != v->getPaintWidth()) {
1951 cerr << "(cache width " << cw 1951 cerr << "(cache width " << cw
1952 << " != " << v->width(); 1952 << " != " << v->getPaintWidth();
1953 } 1953 }
1954 if (ch != v->height()) { 1954 if (ch != v->getPaintHeight()) {
1955 cerr << "(cache height " << ch 1955 cerr << "(cache height " << ch
1956 << " != " << v->height(); 1956 << " != " << v->getPaintHeight();
1957 } 1957 }
1958 #endif 1958 #endif
1959 cache.validArea = QRect(); 1959 cache.validArea = QRect();
1960 // recreateWholeImageCache = true; 1960 // recreateWholeImageCache = true;
1961 } 1961 }
1975 #endif 1975 #endif
1976 } 1976 }
1977 1977
1978 if (recreateWholeImageCache) { 1978 if (recreateWholeImageCache) {
1979 x0 = 0; 1979 x0 = 0;
1980 x1 = v->width(); 1980 x1 = v->getPaintWidth();
1981 } 1981 }
1982 1982
1983 struct timeval tv; 1983 struct timeval tv;
1984 (void)gettimeofday(&tv, 0); 1984 (void)gettimeofday(&tv, 0);
1985 RealTime mainPaintStart = RealTime::fromTimeval(tv); 1985 RealTime mainPaintStart = RealTime::fromTimeval(tv);
2019 // Smaller heights can be used when painting direct from cache 2019 // Smaller heights can be used when painting direct from cache
2020 // (further up in this function), but we want to ensure the cache 2020 // (further up in this function), but we want to ensure the cache
2021 // is coherent without having to worry about vertical matching of 2021 // is coherent without having to worry about vertical matching of
2022 // required and valid areas as well as horizontal. 2022 // required and valid areas as well as horizontal.
2023 2023
2024 int h = v->height(); 2024 int h = v->getPaintHeight();
2025 2025
2026 if (cache.validArea.width() > 0) { 2026 if (cache.validArea.width() > 0) {
2027 2027
2028 // If part of the cache is known to be valid, select a strip 2028 // If part of the cache is known to be valid, select a strip
2029 // immediately to left or right of the valid part 2029 // immediately to left or right of the valid part
2326 2326
2327 Profiler profiler2("SpectrogramLayer::paint: draw image"); 2327 Profiler profiler2("SpectrogramLayer::paint: draw image");
2328 2328
2329 if (recreateWholeImageCache) { 2329 if (recreateWholeImageCache) {
2330 #ifdef DEBUG_SPECTROGRAM_REPAINT 2330 #ifdef DEBUG_SPECTROGRAM_REPAINT
2331 SVDEBUG << "Recreating image cache: width = " << v->width() 2331 SVDEBUG << "Recreating image cache: width = " << v->getPaintWidth()
2332 << ", height = " << h << endl; 2332 << ", height = " << h << endl;
2333 #endif 2333 #endif
2334 cache.image = QImage(v->width(), h, QImage::Format_ARGB32_Premultiplied); 2334 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied);
2335 } 2335 }
2336 2336
2337 if (w > 0) { 2337 if (w > 0) {
2338 #ifdef DEBUG_SPECTROGRAM_REPAINT 2338 #ifdef DEBUG_SPECTROGRAM_REPAINT
2339 SVDEBUG << "Painting " << w << "x" << h 2339 SVDEBUG << "Painting " << w << "x" << h
2405 if (cache.validArea.x() > 0) { 2405 if (cache.validArea.x() > 0) {
2406 #ifdef DEBUG_SPECTROGRAM_REPAINT 2406 #ifdef DEBUG_SPECTROGRAM_REPAINT
2407 SVDEBUG << "SpectrogramLayer::paint() updating left (0, " 2407 SVDEBUG << "SpectrogramLayer::paint() updating left (0, "
2408 << cache.validArea.x() << ")" << endl; 2408 << cache.validArea.x() << ")" << endl;
2409 #endif 2409 #endif
2410 v->update(0, 0, cache.validArea.x(), h); 2410 v->getView()->update(0, 0, cache.validArea.x(), h);
2411 } 2411 }
2412 2412
2413 if (cache.validArea.x() + cache.validArea.width() < 2413 if (cache.validArea.x() + cache.validArea.width() <
2414 cache.image.width()) { 2414 cache.image.width()) {
2415 #ifdef DEBUG_SPECTROGRAM_REPAINT 2415 #ifdef DEBUG_SPECTROGRAM_REPAINT
2418 << ", " 2418 << ", "
2419 << cache.image.width() - (cache.validArea.x() + 2419 << cache.image.width() - (cache.validArea.x() +
2420 cache.validArea.width()) 2420 cache.validArea.width())
2421 << ")" << endl; 2421 << ")" << endl;
2422 #endif 2422 #endif
2423 v->update(cache.validArea.x() + cache.validArea.width(), 2423 v->getView()->update(cache.validArea.x() + cache.validArea.width(),
2424 0, 2424 0,
2425 cache.image.width() - (cache.validArea.x() + 2425 cache.image.width() - (cache.validArea.x() +
2426 cache.validArea.width()), 2426 cache.validArea.width()),
2427 h); 2427 h);
2428 } 2428 }
2429 } else { 2429 } else {
2430 // overallMagChanged 2430 // overallMagChanged
2431 cerr << "\noverallMagChanged - updating all\n" << endl; 2431 cerr << "\noverallMagChanged - updating all\n" << endl;
2432 cache.validArea = QRect(); 2432 cache.validArea = QRect();
2433 v->update(); 2433 v->getView()->update();
2434 } 2434 }
2435 } 2435 }
2436 2436
2437 illuminateLocalFeatures(v, paint); 2437 illuminateLocalFeatures(v, paint);
2438 2438
2448 2448
2449 //!!! if (fftSuspended) fft->resume(); 2449 //!!! if (fftSuspended) fft->resume();
2450 } 2450 }
2451 2451
2452 bool 2452 bool
2453 SpectrogramLayer::paintDrawBufferPeakFrequencies(View *v, 2453 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v,
2454 int w, 2454 int w,
2455 int h, 2455 int h,
2456 const vector<int> &binforx, 2456 const vector<int> &binforx,
2457 int minbin, 2457 int minbin,
2458 int maxbin, 2458 int maxbin,
2576 2576
2577 return true; 2577 return true;
2578 } 2578 }
2579 2579
2580 bool 2580 bool
2581 SpectrogramLayer::paintDrawBuffer(View *v, 2581 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v,
2582 int w, 2582 int w,
2583 int h, 2583 int h,
2584 const vector<int> &binforx, 2584 const vector<int> &binforx,
2585 const vector<double> &binfory, 2585 const vector<double> &binfory,
2586 bool usePeaksCache, 2586 bool usePeaksCache,
2817 2817
2818 return true; 2818 return true;
2819 } 2819 }
2820 2820
2821 void 2821 void
2822 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const 2822 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const
2823 { 2823 {
2824 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); 2824 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures");
2825 2825
2826 QPoint localPos; 2826 QPoint localPos;
2827 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { 2827 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) {
2856 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1); 2856 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1);
2857 } 2857 }
2858 } 2858 }
2859 2859
2860 double 2860 double
2861 SpectrogramLayer::getYForFrequency(const View *v, double frequency) const 2861 SpectrogramLayer::getYForFrequency(const LayerGeometryProvider *v, double frequency) const
2862 { 2862 {
2863 return v->getYForFrequency(frequency, 2863 return v->getYForFrequency(frequency,
2864 getEffectiveMinFrequency(), 2864 getEffectiveMinFrequency(),
2865 getEffectiveMaxFrequency(), 2865 getEffectiveMaxFrequency(),
2866 m_frequencyScale == LogFrequencyScale); 2866 m_frequencyScale == LogFrequencyScale);
2867 } 2867 }
2868 2868
2869 double 2869 double
2870 SpectrogramLayer::getFrequencyForY(const View *v, int y) const 2870 SpectrogramLayer::getFrequencyForY(const LayerGeometryProvider *v, int y) const
2871 { 2871 {
2872 return v->getFrequencyForY(y, 2872 return v->getFrequencyForY(y,
2873 getEffectiveMinFrequency(), 2873 getEffectiveMinFrequency(),
2874 getEffectiveMaxFrequency(), 2874 getEffectiveMaxFrequency(),
2875 m_frequencyScale == LogFrequencyScale); 2875 m_frequencyScale == LogFrequencyScale);
2876 } 2876 }
2877 2877
2878 int 2878 int
2879 SpectrogramLayer::getCompletion(View *v) const 2879 SpectrogramLayer::getCompletion(LayerGeometryProvider *v) const
2880 { 2880 {
2881 if (m_updateTimer == 0) return 100; 2881 if (m_updateTimer == 0) return 100;
2882 if (m_fftModels.find(v) == m_fftModels.end()) return 100; 2882 if (m_fftModels.find(v) == m_fftModels.end()) return 100;
2883 2883
2884 int completion = m_fftModels[v].first->getCompletion(); 2884 int completion = m_fftModels[v].first->getCompletion();
2887 #endif 2887 #endif
2888 return completion; 2888 return completion;
2889 } 2889 }
2890 2890
2891 QString 2891 QString
2892 SpectrogramLayer::getError(View *v) const 2892 SpectrogramLayer::getError(LayerGeometryProvider *v) const
2893 { 2893 {
2894 if (m_fftModels.find(v) == m_fftModels.end()) return ""; 2894 if (m_fftModels.find(v) == m_fftModels.end()) return "";
2895 return m_fftModels[v].first->getError(); 2895 return m_fftModels[v].first->getError();
2896 } 2896 }
2897 2897
2951 2951
2952 return true; 2952 return true;
2953 } 2953 }
2954 2954
2955 bool 2955 bool
2956 SpectrogramLayer::getYScaleValue(const View *v, int y, 2956 SpectrogramLayer::getYScaleValue(const LayerGeometryProvider *v, int y,
2957 double &value, QString &unit) const 2957 double &value, QString &unit) const
2958 { 2958 {
2959 value = getFrequencyForY(v, y); 2959 value = getFrequencyForY(v, y);
2960 unit = "Hz"; 2960 unit = "Hz";
2961 return true; 2961 return true;
2962 } 2962 }
2963 2963
2964 bool 2964 bool
2965 SpectrogramLayer::snapToFeatureFrame(View *, 2965 SpectrogramLayer::snapToFeatureFrame(LayerGeometryProvider *,
2966 sv_frame_t &frame, 2966 sv_frame_t &frame,
2967 int &resolution, 2967 int &resolution,
2968 SnapType snap) const 2968 SnapType snap) const
2969 { 2969 {
2970 resolution = getWindowIncrement(); 2970 resolution = getWindowIncrement();
2983 2983
2984 return true; 2984 return true;
2985 } 2985 }
2986 2986
2987 void 2987 void
2988 SpectrogramLayer::measureDoubleClick(View *v, QMouseEvent *e) 2988 SpectrogramLayer::measureDoubleClick(LayerGeometryProvider *v, QMouseEvent *e)
2989 { 2989 {
2990 ImageCache &cache = m_imageCaches[v]; 2990 ImageCache &cache = m_imageCaches[v];
2991 2991
2992 cerr << "cache width: " << cache.image.width() << ", height: " 2992 cerr << "cache width: " << cache.image.width() << ", height: "
2993 << cache.image.height() << endl; 2993 << cache.image.height() << endl;
3003 (new AddMeasurementRectCommand(this, mr)); 3003 (new AddMeasurementRectCommand(this, mr));
3004 } 3004 }
3005 } 3005 }
3006 3006
3007 bool 3007 bool
3008 SpectrogramLayer::getCrosshairExtents(View *v, QPainter &paint, 3008 SpectrogramLayer::getCrosshairExtents(LayerGeometryProvider *v, QPainter &paint,
3009 QPoint cursorPos, 3009 QPoint cursorPos,
3010 std::vector<QRect> &extents) const 3010 std::vector<QRect> &extents) const
3011 { 3011 {
3012 QRect vertical(cursorPos.x() - 12, 0, 12, v->height()); 3012 QRect vertical(cursorPos.x() - 12, 0, 12, v->getPaintHeight());
3013 extents.push_back(vertical); 3013 extents.push_back(vertical);
3014 3014
3015 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1); 3015 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1);
3016 extents.push_back(horizontal); 3016 extents.push_back(horizontal);
3017 3017
3026 paint.fontMetrics().width("C#10+50c") + 2, 3026 paint.fontMetrics().width("C#10+50c") + 2,
3027 paint.fontMetrics().height()); 3027 paint.fontMetrics().height());
3028 extents.push_back(pitch); 3028 extents.push_back(pitch);
3029 3029
3030 QRect rt(cursorPos.x(), 3030 QRect rt(cursorPos.x(),
3031 v->height() - paint.fontMetrics().height() - 2, 3031 v->getPaintHeight() - paint.fontMetrics().height() - 2,
3032 paint.fontMetrics().width("1234.567 s"), 3032 paint.fontMetrics().width("1234.567 s"),
3033 paint.fontMetrics().height()); 3033 paint.fontMetrics().height());
3034 extents.push_back(rt); 3034 extents.push_back(rt);
3035 3035
3036 int w(paint.fontMetrics().width("1234567890") + 2); 3036 int w(paint.fontMetrics().width("1234567890") + 2);
3037 QRect frame(cursorPos.x() - w - 2, 3037 QRect frame(cursorPos.x() - w - 2,
3038 v->height() - paint.fontMetrics().height() - 2, 3038 v->getPaintHeight() - paint.fontMetrics().height() - 2,
3039 w, 3039 w,
3040 paint.fontMetrics().height()); 3040 paint.fontMetrics().height());
3041 extents.push_back(frame); 3041 extents.push_back(frame);
3042 3042
3043 return true; 3043 return true;
3044 } 3044 }
3045 3045
3046 void 3046 void
3047 SpectrogramLayer::paintCrosshairs(View *v, QPainter &paint, 3047 SpectrogramLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint,
3048 QPoint cursorPos) const 3048 QPoint cursorPos) const
3049 { 3049 {
3050 paint.save(); 3050 paint.save();
3051 3051
3052 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint); 3052 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint);
3057 paint.setFont(fn); 3057 paint.setFont(fn);
3058 } 3058 }
3059 paint.setPen(m_crosshairColour); 3059 paint.setPen(m_crosshairColour);
3060 3060
3061 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); 3061 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y());
3062 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height()); 3062 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->getPaintHeight());
3063 3063
3064 double fundamental = getFrequencyForY(v, cursorPos.y()); 3064 double fundamental = getFrequencyForY(v, cursorPos.y());
3065 3065
3066 v->drawVisibleText(paint, 3066 v->drawVisibleText(paint,
3067 sw + 2, 3067 sw + 2,
3082 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); 3082 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate());
3083 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); 3083 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str());
3084 QString frameLabel = QString("%1").arg(frame); 3084 QString frameLabel = QString("%1").arg(frame);
3085 v->drawVisibleText(paint, 3085 v->drawVisibleText(paint,
3086 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, 3086 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2,
3087 v->height() - 2, 3087 v->getPaintHeight() - 2,
3088 frameLabel, 3088 frameLabel,
3089 View::OutlinedText); 3089 View::OutlinedText);
3090 v->drawVisibleText(paint, 3090 v->drawVisibleText(paint,
3091 cursorPos.x() + 2, 3091 cursorPos.x() + 2,
3092 v->height() - 2, 3092 v->getPaintHeight() - 2,
3093 rtLabel, 3093 rtLabel,
3094 View::OutlinedText); 3094 View::OutlinedText);
3095 3095
3096 int harmonic = 2; 3096 int harmonic = 2;
3097 3097
3098 while (harmonic < 100) { 3098 while (harmonic < 100) {
3099 3099
3100 int hy = int(lrint(getYForFrequency(v, fundamental * harmonic))); 3100 int hy = int(lrint(getYForFrequency(v, fundamental * harmonic)));
3101 if (hy < 0 || hy > v->height()) break; 3101 if (hy < 0 || hy > v->getPaintHeight()) break;
3102 3102
3103 int len = 7; 3103 int len = 7;
3104 3104
3105 if (harmonic % 2 == 0) { 3105 if (harmonic % 2 == 0) {
3106 if (harmonic % 4 == 0) { 3106 if (harmonic % 4 == 0) {
3120 3120
3121 paint.restore(); 3121 paint.restore();
3122 } 3122 }
3123 3123
3124 QString 3124 QString
3125 SpectrogramLayer::getFeatureDescription(View *v, QPoint &pos) const 3125 SpectrogramLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
3126 { 3126 {
3127 int x = pos.x(); 3127 int x = pos.x();
3128 int y = pos.y(); 3128 int y = pos.y();
3129 3129
3130 if (!m_model || !m_model->isOK()) return ""; 3130 if (!m_model || !m_model->isOK()) return "";
3242 3242
3243 return cw; 3243 return cw;
3244 } 3244 }
3245 3245
3246 int 3246 int
3247 SpectrogramLayer::getVerticalScaleWidth(View *, bool detailed, QPainter &paint) const 3247 SpectrogramLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool detailed, QPainter &paint) const
3248 { 3248 {
3249 if (!m_model || !m_model->isOK()) return 0; 3249 if (!m_model || !m_model->isOK()) return 0;
3250 3250
3251 int cw = 0; 3251 int cw = 0;
3252 if (detailed) cw = getColourScaleWidth(paint); 3252 if (detailed) cw = getColourScaleWidth(paint);
3263 3263
3264 return cw + tickw + tw + 13; 3264 return cw + tickw + tw + 13;
3265 } 3265 }
3266 3266
3267 void 3267 void
3268 SpectrogramLayer::paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const 3268 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const
3269 { 3269 {
3270 if (!m_model || !m_model->isOK()) { 3270 if (!m_model || !m_model->isOK()) {
3271 return; 3271 return;
3272 } 3272 }
3273 3273
3377 3377
3378 paint.drawLine(cw + 7, 0, cw + 7, h); 3378 paint.drawLine(cw + 7, 0, cw + 7, h);
3379 3379
3380 int bin = -1; 3380 int bin = -1;
3381 3381
3382 for (int y = 0; y < v->height(); ++y) { 3382 for (int y = 0; y < v->getPaintHeight(); ++y) {
3383 3383
3384 double q0, q1; 3384 double q0, q1;
3385 if (!getYBinRange(v, v->height() - y, q0, q1)) continue; 3385 if (!getYBinRange(v, v->getPaintHeight() - y, q0, q1)) continue;
3386 3386
3387 int vy; 3387 int vy;
3388 3388
3389 if (int(q0) > bin) { 3389 if (int(q0) > bin) {
3390 vy = y; 3390 vy = y;
3594 if (!m_model) return 0; 3594 if (!m_model) return 0;
3595 return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize); 3595 return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize);
3596 } 3596 }
3597 3597
3598 void 3598 void
3599 SpectrogramLayer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const 3599 SpectrogramLayer::updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const
3600 { 3600 {
3601 int y0 = 0; 3601 int y0 = 0;
3602 if (r.startY > 0.0) y0 = int(getYForFrequency(v, r.startY)); 3602 if (r.startY > 0.0) y0 = int(getYForFrequency(v, r.startY));
3603 3603
3604 int y1 = y0; 3604 int y1 = y0;
3608 3608
3609 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0); 3609 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
3610 } 3610 }
3611 3611
3612 void 3612 void
3613 SpectrogramLayer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const 3613 SpectrogramLayer::setMeasureRectYCoord(LayerGeometryProvider *v, MeasureRect &r, bool start, int y) const
3614 { 3614 {
3615 if (start) { 3615 if (start) {
3616 r.startY = getFrequencyForY(v, y); 3616 r.startY = getFrequencyForY(v, y);
3617 r.endY = r.startY; 3617 r.endY = r.startY;
3618 } else { 3618 } else {