comparison layer/SpectrogramLayer.cpp @ 44:ad214997dddb

* Refactor Layer classes so as no longer to store a single View pointer; instead they need to be able to draw themselves on any View on demand. Layers with caches (e.g. spectrogram) will need to be further refactored so as to maintain a per-View cache * Begin refactoring MainWindow by pulling out the document stuff (set of layers, models etc) into a Document class. Not yet in use. This revision is fairly unstable.
author Chris Cannam
date Thu, 02 Mar 2006 16:58:49 +0000
parents 78515b1e29eb
children 25a2915d351d
comparison
equal deleted inserted replaced
43:78515b1e29eb 44:ad214997dddb
29 #include <cmath> 29 #include <cmath>
30 30
31 //#define DEBUG_SPECTROGRAM_REPAINT 1 31 //#define DEBUG_SPECTROGRAM_REPAINT 1
32 32
33 33
34 SpectrogramLayer::SpectrogramLayer(View *w, Configuration config) : 34 SpectrogramLayer::SpectrogramLayer(Configuration config) :
35 Layer(w), 35 Layer(),
36 m_model(0), 36 m_model(0),
37 m_channel(0), 37 m_channel(0),
38 m_windowSize(1024), 38 m_windowSize(1024),
39 m_windowType(HanningWindow), 39 m_windowType(HanningWindow),
40 m_windowOverlap(50), 40 m_windowOverlap(50),
52 m_cacheInvalid(true), 52 m_cacheInvalid(true),
53 m_pixmapCache(0), 53 m_pixmapCache(0),
54 m_pixmapCacheInvalid(true), 54 m_pixmapCacheInvalid(true),
55 m_fillThread(0), 55 m_fillThread(0),
56 m_updateTimer(0), 56 m_updateTimer(0),
57 m_candidateFillStartFrame(0),
57 m_lastFillExtent(0), 58 m_lastFillExtent(0),
58 m_exiting(false) 59 m_exiting(false)
59 { 60 {
60 if (config == MelodicRange) { 61 if (config == MelodicRange) {
61 setWindowSize(8192); 62 setWindowSize(8192);
72 setFrequencyScale(LogFrequencyScale); 73 setFrequencyScale(LogFrequencyScale);
73 setColourScale(MeterColourScale); 74 setColourScale(MeterColourScale);
74 setBinDisplay(PeakFrequencies); 75 setBinDisplay(PeakFrequencies);
75 setNormalizeColumns(true); 76 setNormalizeColumns(true);
76 } 77 }
77
78 if (m_view) m_view->setLightBackground(false);
79 m_view->addLayer(this);
80 } 78 }
81 79
82 SpectrogramLayer::~SpectrogramLayer() 80 SpectrogramLayer::~SpectrogramLayer()
83 { 81 {
84 delete m_updateTimer; 82 delete m_updateTimer;
412 if (value == -50) setThreshold(0.0); 410 if (value == -50) setThreshold(0.0);
413 else setThreshold(AudioLevel::dB_to_multiplier(value)); 411 else setThreshold(AudioLevel::dB_to_multiplier(value));
414 } else if (name == tr("Colour Rotation")) { 412 } else if (name == tr("Colour Rotation")) {
415 setColourRotation(value); 413 setColourRotation(value);
416 } else if (name == tr("Colour")) { 414 } else if (name == tr("Colour")) {
417 if (m_view) m_view->setLightBackground(value == 2); 415 //!!! if (v) v->setLightBackground(value == 2);
418 switch (value) { 416 switch (value) {
419 default: 417 default:
420 case 0: setColourScheme(DefaultColours); break; 418 case 0: setColourScheme(DefaultColours); break;
421 case 1: setColourScheme(WhiteOnBlack); break; 419 case 1: setColourScheme(WhiteOnBlack); break;
422 case 2: setColourScheme(BlackOnWhite); break; 420 case 2: setColourScheme(BlackOnWhite); break;
798 { 796 {
799 return m_normalizeColumns; 797 return m_normalizeColumns;
800 } 798 }
801 799
802 void 800 void
803 SpectrogramLayer::setLayerDormant(bool dormant) 801 SpectrogramLayer::setLayerDormant(const bool dormant)
804 { 802 {
805 if (dormant == m_dormant) return; 803 if (dormant == m_dormant) return;
806 804
807 if (dormant) { 805 if (dormant) {
808 806
891 emit modelChanged(m_lastFillExtent, fillExtent); 889 emit modelChanged(m_lastFillExtent, fillExtent);
892 m_pixmapCacheInvalid = true; 890 m_pixmapCacheInvalid = true;
893 m_lastFillExtent = fillExtent; 891 m_lastFillExtent = fillExtent;
894 } 892 }
895 } else { 893 } else {
896 if (m_view) { 894 // if (v) {
897 size_t sf = 0; 895 size_t sf = 0;
898 if (m_view->getStartFrame() > 0) sf = m_view->getStartFrame(); 896 //!!! if (v->getStartFrame() > 0) sf = v->getStartFrame();
899 #ifdef DEBUG_SPECTROGRAM_REPAINT 897 #ifdef DEBUG_SPECTROGRAM_REPAINT
900 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" 898 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged("
901 << sf << "," << m_view->getEndFrame() << ")" << std::endl; 899 << sf << "," << m_model->getEndFrame() << ")" << std::endl;
902 #endif 900 #endif
903 emit modelChanged(sf, m_view->getEndFrame()); 901 emit modelChanged(sf, m_model->getEndFrame());
904 m_pixmapCacheInvalid = true; 902 m_pixmapCacheInvalid = true;
905 } 903 // }
906 m_lastFillExtent = fillExtent; 904 m_lastFillExtent = fillExtent;
907 } 905 }
908 } 906 }
909 } 907 }
910 908
1195 { 1193 {
1196 } 1194 }
1197 1195
1198 SpectrogramLayer::Cache::~Cache() 1196 SpectrogramLayer::Cache::~Cache()
1199 { 1197 {
1200 for (size_t i = 0; i < m_height; ++i) { 1198 for (size_t i = 0; i < m_width; ++i) {
1201 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]); 1199 if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
1202 if (m_phase && m_phase[i]) free(m_phase[i]); 1200 if (m_phase && m_phase[i]) free(m_phase[i]);
1203 } 1201 }
1204 1202
1205 if (m_magnitude) free(m_magnitude); 1203 if (m_magnitude) free(m_magnitude);
1226 } 1224 }
1227 1225
1228 void 1226 void
1229 SpectrogramLayer::Cache::resize(uint16_t **&array, size_t width, size_t height) 1227 SpectrogramLayer::Cache::resize(uint16_t **&array, size_t width, size_t height)
1230 { 1228 {
1231 for (size_t i = height; i < m_height; ++i) { 1229 for (size_t i = width; i < m_width; ++i) {
1232 free(array[i]); 1230 free(array[i]);
1233 } 1231 }
1234 1232
1235 if (height != m_height) { 1233 if (width != m_width) {
1236 array = (uint16_t **)realloc(array, height * sizeof(uint16_t *)); 1234 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
1237 if (!array) throw std::bad_alloc(); 1235 if (!array) throw std::bad_alloc();
1238 MUNLOCK(array, height * sizeof(uint16_t *)); 1236 MUNLOCK(array, width * sizeof(uint16_t *));
1239 } 1237 }
1240 1238
1241 for (size_t i = m_height; i < height; ++i) { 1239 for (size_t i = m_width; i < width; ++i) {
1242 array[i] = 0; 1240 array[i] = 0;
1243 } 1241 }
1244 1242
1245 for (size_t i = 0; i < height; ++i) { 1243 for (size_t i = 0; i < width; ++i) {
1246 array[i] = (uint16_t *)realloc(array[i], width * sizeof(uint16_t)); 1244 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
1247 if (!array[i]) throw std::bad_alloc(); 1245 if (!array[i]) throw std::bad_alloc();
1248 MUNLOCK(array[i], width * sizeof(uint16_t)); 1246 MUNLOCK(array[i], height * sizeof(uint16_t));
1249 } 1247 }
1250 } 1248 }
1251 1249
1252 void 1250 void
1253 SpectrogramLayer::Cache::reset() 1251 SpectrogramLayer::Cache::reset()
1254 { 1252 {
1255 for (size_t x = 0; x < m_width; ++x) { 1253 for (size_t x = 0; x < m_width; ++x) {
1256 for (size_t y = 0; y < m_height; ++y) { 1254 for (size_t y = 0; y < m_height; ++y) {
1257 m_magnitude[y][x] = 0; 1255 m_magnitude[x][y] = 0;
1258 m_phase[y][x] = 0; 1256 m_phase[x][y] = 0;
1259 } 1257 }
1260 m_factor[x] = 1.0; 1258 m_factor[x] = 1.0;
1261 } 1259 }
1262 } 1260 }
1263 1261
1302 1300
1303 WindowType windowType = m_layer.m_windowType; 1301 WindowType windowType = m_layer.m_windowType;
1304 size_t windowSize = m_layer.m_windowSize; 1302 size_t windowSize = m_layer.m_windowSize;
1305 size_t windowIncrement = m_layer.getWindowIncrement(); 1303 size_t windowIncrement = m_layer.getWindowIncrement();
1306 1304
1307 size_t visibleStart = start; 1305 size_t visibleStart = m_layer.m_candidateFillStartFrame;
1308 size_t visibleEnd = end; 1306 visibleStart = (visibleStart / windowIncrement) * windowIncrement;
1309
1310 if (m_layer.m_view) {
1311 if (m_layer.m_view->getStartFrame() < 0) {
1312 visibleStart = 0;
1313 } else {
1314 visibleStart = m_layer.m_view->getStartFrame();
1315 visibleStart = (visibleStart / windowIncrement) *
1316 windowIncrement;
1317 }
1318 visibleEnd = m_layer.m_view->getEndFrame();
1319 }
1320 1307
1321 size_t width = (end - start) / windowIncrement + 1; 1308 size_t width = (end - start) / windowIncrement + 1;
1322 size_t height = windowSize / 2; 1309 size_t height = windowSize / 2;
1323 1310
1324 if (!m_layer.m_cache) { 1311 if (!m_layer.m_cache) {
1361 1348
1362 int counter = 0; 1349 int counter = 0;
1363 int updateAt = (end / windowIncrement) / 20; 1350 int updateAt = (end / windowIncrement) / 20;
1364 if (updateAt < 100) updateAt = 100; 1351 if (updateAt < 100) updateAt = 100;
1365 1352
1366 bool doVisibleFirst = (visibleStart != start && visibleEnd != end); 1353 bool doVisibleFirst = (visibleStart != start);
1367 1354
1368 if (doVisibleFirst) { 1355 if (doVisibleFirst) {
1369 1356
1370 for (size_t f = visibleStart; f < visibleEnd; f += windowIncrement) { 1357 for (size_t f = visibleStart; f < end; f += windowIncrement) {
1371
1372 m_layer.fillCacheColumn(int((f - start) / windowIncrement),
1373 input, output, plan,
1374 windowSize, windowIncrement,
1375 windower);
1376
1377 if (m_layer.m_cacheInvalid || m_layer.m_exiting) {
1378 interrupted = true;
1379 m_fillExtent = 0;
1380 break;
1381 }
1382
1383 if (++counter == updateAt ||
1384 (f >= visibleEnd - 1 && f < visibleEnd + windowIncrement)) {
1385 if (f < end) m_fillExtent = f;
1386 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) /
1387 float(end - start)));
1388 counter = 0;
1389 }
1390 }
1391
1392 std::cerr << "SpectrogramLayer::CacheFillThread::run: visible bit done" << std::endl;
1393 m_layer.m_view->update();
1394 }
1395
1396 if (!interrupted && doVisibleFirst) {
1397
1398 for (size_t f = visibleEnd; f < end; f += windowIncrement) {
1399 1358
1400 m_layer.fillCacheColumn(int((f - start) / windowIncrement), 1359 m_layer.fillCacheColumn(int((f - start) / windowIncrement),
1401 input, output, plan, 1360 input, output, plan,
1402 windowSize, windowIncrement, 1361 windowSize, windowIncrement,
1403 windower); 1362 windower);
1438 interrupted = true; 1397 interrupted = true;
1439 m_fillExtent = 0; 1398 m_fillExtent = 0;
1440 break; 1399 break;
1441 } 1400 }
1442 1401
1443 if (++counter == updateAt || 1402 if (++counter == updateAt) {
1444 (f >= visibleEnd - 1 && f < visibleEnd + windowIncrement)) {
1445 m_fillExtent = f; 1403 m_fillExtent = f;
1446 m_fillCompletion = baseCompletion + 1404 m_fillCompletion = baseCompletion +
1447 size_t(100 * fabsf(float(f - start) / 1405 size_t(100 * fabsf(float(f - start) /
1448 float(end - start))); 1406 float(end - start)));
1449 counter = 0; 1407 counter = 0;
1496 1454
1497 return maxf; 1455 return maxf;
1498 } 1456 }
1499 1457
1500 bool 1458 bool
1501 SpectrogramLayer::getYBinRange(int y, float &q0, float &q1) const 1459 SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const
1502 { 1460 {
1503 int h = m_view->height(); 1461 int h = v->height();
1504 if (y < 0 || y >= h) return false; 1462 if (y < 0 || y >= h) return false;
1505 1463
1506 int sr = m_model->getSampleRate(); 1464 int sr = m_model->getSampleRate();
1507 float minf = getEffectiveMinFrequency(); 1465 float minf = getEffectiveMinFrequency();
1508 float maxf = getEffectiveMaxFrequency(); 1466 float maxf = getEffectiveMaxFrequency();
1509 1467
1510 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1468 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1511 1469
1512 q0 = m_view->getFrequencyForY(y, minf, maxf, logarithmic); 1470 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic);
1513 q1 = m_view->getFrequencyForY(y - 1, minf, maxf, logarithmic); 1471 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic);
1514 1472
1515 // Now map these on to actual bins 1473 // Now map these on to actual bins
1516 1474
1517 int b0 = int((q0 * m_windowSize) / sr); 1475 int b0 = int((q0 * m_windowSize) / sr);
1518 int b1 = int((q1 * m_windowSize) / sr); 1476 int b1 = int((q1 * m_windowSize) / sr);
1526 1484
1527 return true; 1485 return true;
1528 } 1486 }
1529 1487
1530 bool 1488 bool
1531 SpectrogramLayer::getXBinRange(int x, float &s0, float &s1) const 1489 SpectrogramLayer::getXBinRange(View *v, int x, float &s0, float &s1) const
1532 { 1490 {
1533 size_t modelStart = m_model->getStartFrame(); 1491 size_t modelStart = m_model->getStartFrame();
1534 size_t modelEnd = m_model->getEndFrame(); 1492 size_t modelEnd = m_model->getEndFrame();
1535 1493
1536 // Each pixel column covers an exact range of sample frames: 1494 // Each pixel column covers an exact range of sample frames:
1537 int f0 = getFrameForX(x) - modelStart; 1495 int f0 = v->getFrameForX(x) - modelStart;
1538 int f1 = getFrameForX(x + 1) - modelStart - 1; 1496 int f1 = v->getFrameForX(x + 1) - modelStart - 1;
1539 1497
1540 if (f1 < int(modelStart) || f0 > int(modelEnd)) { 1498 if (f1 < int(modelStart) || f0 > int(modelEnd)) {
1541 return false; 1499 return false;
1542 } 1500 }
1543 1501
1550 1508
1551 return true; 1509 return true;
1552 } 1510 }
1553 1511
1554 bool 1512 bool
1555 SpectrogramLayer::getXBinSourceRange(int x, RealTime &min, RealTime &max) const 1513 SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const
1556 { 1514 {
1557 float s0 = 0, s1 = 0; 1515 float s0 = 0, s1 = 0;
1558 if (!getXBinRange(x, s0, s1)) return false; 1516 if (!getXBinRange(v, x, s0, s1)) return false;
1559 1517
1560 int s0i = int(s0 + 0.001); 1518 int s0i = int(s0 + 0.001);
1561 int s1i = int(s1); 1519 int s1i = int(s1);
1562 1520
1563 int windowIncrement = getWindowIncrement(); 1521 int windowIncrement = getWindowIncrement();
1569 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); 1527 max = RealTime::frame2RealTime(w1, m_model->getSampleRate());
1570 return true; 1528 return true;
1571 } 1529 }
1572 1530
1573 bool 1531 bool
1574 SpectrogramLayer::getYBinSourceRange(int y, float &freqMin, float &freqMax) 1532 SpectrogramLayer::getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax)
1575 const 1533 const
1576 { 1534 {
1577 float q0 = 0, q1 = 0; 1535 float q0 = 0, q1 = 0;
1578 if (!getYBinRange(y, q0, q1)) return false; 1536 if (!getYBinRange(v, y, q0, q1)) return false;
1579 1537
1580 int q0i = int(q0 + 0.001); 1538 int q0i = int(q0 + 0.001);
1581 int q1i = int(q1); 1539 int q1i = int(q1);
1582 1540
1583 int sr = m_model->getSampleRate(); 1541 int sr = m_model->getSampleRate();
1589 } 1547 }
1590 return true; 1548 return true;
1591 } 1549 }
1592 1550
1593 bool 1551 bool
1594 SpectrogramLayer::getAdjustedYBinSourceRange(int x, int y, 1552 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y,
1595 float &freqMin, float &freqMax, 1553 float &freqMin, float &freqMax,
1596 float &adjFreqMin, float &adjFreqMax) 1554 float &adjFreqMin, float &adjFreqMax)
1597 const 1555 const
1598 { 1556 {
1599 float s0 = 0, s1 = 0; 1557 float s0 = 0, s1 = 0;
1600 if (!getXBinRange(x, s0, s1)) return false; 1558 if (!getXBinRange(v, x, s0, s1)) return false;
1601 1559
1602 float q0 = 0, q1 = 0; 1560 float q0 = 0, q1 = 0;
1603 if (!getYBinRange(y, q0, q1)) return false; 1561 if (!getYBinRange(v, y, q0, q1)) return false;
1604 1562
1605 int s0i = int(s0 + 0.001); 1563 int s0i = int(s0 + 0.001);
1606 int s1i = int(s1); 1564 int s1i = int(s1);
1607 1565
1608 int q0i = int(q0 + 0.001); 1566 int q0i = int(q0 + 0.001);
1659 1617
1660 return haveAdj; 1618 return haveAdj;
1661 } 1619 }
1662 1620
1663 bool 1621 bool
1664 SpectrogramLayer::getXYBinSourceRange(int x, int y, 1622 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y,
1665 float &min, float &max, 1623 float &min, float &max,
1666 float &phaseMin, float &phaseMax) const 1624 float &phaseMin, float &phaseMax) const
1667 { 1625 {
1668 float q0 = 0, q1 = 0; 1626 float q0 = 0, q1 = 0;
1669 if (!getYBinRange(y, q0, q1)) return false; 1627 if (!getYBinRange(v, y, q0, q1)) return false;
1670 1628
1671 float s0 = 0, s1 = 0; 1629 float s0 = 0, s1 = 0;
1672 if (!getXBinRange(x, s0, s1)) return false; 1630 if (!getXBinRange(v, x, s0, s1)) return false;
1673 1631
1674 int q0i = int(q0 + 0.001); 1632 int q0i = int(q0 + 0.001);
1675 int q1i = int(q1); 1633 int q1i = int(q1);
1676 1634
1677 int s0i = int(s0 + 0.001); 1635 int s0i = int(s0 + 0.001);
1720 1678
1721 return rv; 1679 return rv;
1722 } 1680 }
1723 1681
1724 void 1682 void
1725 SpectrogramLayer::paint(QPainter &paint, QRect rect) const 1683 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const
1726 { 1684 {
1727 // Profiler profiler("SpectrogramLayer::paint", true); 1685 // Profiler profiler("SpectrogramLayer::paint", true);
1728 #ifdef DEBUG_SPECTROGRAM_REPAINT 1686 #ifdef DEBUG_SPECTROGRAM_REPAINT
1729 std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << m_view->getZoomLevel() << ", m_updateTimer " << m_updateTimer << ", pixmap cache invalid " << m_pixmapCacheInvalid << std::endl; 1687 std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << ", pixmap cache invalid " << m_pixmapCacheInvalid << std::endl;
1730 #endif 1688 #endif
1689
1690 m_candidateFillStartFrame = v->getStartFrame();
1731 1691
1732 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1692 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1733 return; 1693 return;
1734 } 1694 }
1735 1695
1760 1720
1761 #ifdef DEBUG_SPECTROGRAM_REPAINT 1721 #ifdef DEBUG_SPECTROGRAM_REPAINT
1762 std::cerr << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << std::endl; 1722 std::cerr << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << std::endl;
1763 #endif 1723 #endif
1764 1724
1765 long startFrame = m_view->getStartFrame(); 1725 long startFrame = v->getStartFrame();
1766 int zoomLevel = m_view->getZoomLevel(); 1726 int zoomLevel = v->getZoomLevel();
1767 1727
1768 int x0 = 0; 1728 int x0 = 0;
1769 int x1 = m_view->width(); 1729 int x1 = v->width();
1770 int y0 = 0; 1730 int y0 = 0;
1771 int y1 = m_view->height(); 1731 int y1 = v->height();
1772 1732
1773 bool recreateWholePixmapCache = true; 1733 bool recreateWholePixmapCache = true;
1774 1734
1775 if (!m_pixmapCacheInvalid) { 1735 if (!m_pixmapCacheInvalid) {
1776 1736
1778 //scrolling cache in View. Perhaps experiment with 1738 //scrolling cache in View. Perhaps experiment with
1779 //removing it and see if it makes things even quicker (or else 1739 //removing it and see if it makes things even quicker (or else
1780 //make it optional) 1740 //make it optional)
1781 1741
1782 if (int(m_pixmapCacheZoomLevel) == zoomLevel && 1742 if (int(m_pixmapCacheZoomLevel) == zoomLevel &&
1783 m_pixmapCache->width() == m_view->width() && 1743 m_pixmapCache->width() == v->width() &&
1784 m_pixmapCache->height() == m_view->height()) { 1744 m_pixmapCache->height() == v->height()) {
1785 1745
1786 if (getXForFrame(m_pixmapCacheStartFrame) == 1746 if (v->getXForFrame(m_pixmapCacheStartFrame) ==
1787 getXForFrame(startFrame)) { 1747 v->getXForFrame(startFrame)) {
1788 1748
1789 #ifdef DEBUG_SPECTROGRAM_REPAINT 1749 #ifdef DEBUG_SPECTROGRAM_REPAINT
1790 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl; 1750 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl;
1791 #endif 1751 #endif
1792 1752
1800 std::cerr << "SpectrogramLayer: pixmap cache partially OK" << std::endl; 1760 std::cerr << "SpectrogramLayer: pixmap cache partially OK" << std::endl;
1801 #endif 1761 #endif
1802 1762
1803 recreateWholePixmapCache = false; 1763 recreateWholePixmapCache = false;
1804 1764
1805 int dx = getXForFrame(m_pixmapCacheStartFrame) - 1765 int dx = v->getXForFrame(m_pixmapCacheStartFrame) -
1806 getXForFrame(startFrame); 1766 v->getXForFrame(startFrame);
1807 1767
1808 #ifdef DEBUG_SPECTROGRAM_REPAINT 1768 #ifdef DEBUG_SPECTROGRAM_REPAINT
1809 std::cerr << "SpectrogramLayer: dx = " << dx << " (pixmap cache " << m_pixmapCache->width() << "x" << m_pixmapCache->height() << ")" << std::endl; 1769 std::cerr << "SpectrogramLayer: dx = " << dx << " (pixmap cache " << m_pixmapCache->width() << "x" << m_pixmapCache->height() << ")" << std::endl;
1810 #endif 1770 #endif
1811 1771
1912 ydiv[y] = 0.0; 1872 ydiv[y] = 0.0;
1913 } 1873 }
1914 1874
1915 float s0 = 0, s1 = 0; 1875 float s0 = 0, s1 = 0;
1916 1876
1917 if (!getXBinRange(x0 + x, s0, s1)) { 1877 if (!getXBinRange(v, x0 + x, s0, s1)) {
1918 assert(x <= scaled.width()); 1878 assert(x <= scaled.width());
1919 m_mutex.unlock(); 1879 m_mutex.unlock();
1920 continue; 1880 continue;
1921 } 1881 }
1922 1882
1930 1890
1931 float y0 = 0, y1 = 0; 1891 float y0 = 0, y1 = 0;
1932 1892
1933 if (m_binDisplay != PeakFrequencies || 1893 if (m_binDisplay != PeakFrequencies ||
1934 s1i >= int(m_cache->getWidth())) { 1894 s1i >= int(m_cache->getWidth())) {
1935 y0 = m_view->getYForFrequency(f1, minFreq, maxFreq, logarithmic); 1895 y0 = v->getYForFrequency(f1, minFreq, maxFreq, logarithmic);
1936 y1 = m_view->getYForFrequency(f0, minFreq, maxFreq, logarithmic); 1896 y1 = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1937 } 1897 }
1938 1898
1939 for (int s = s0i; s <= s1i; ++s) { 1899 for (int s = s0i; s <= s1i; ++s) {
1940 1900
1941 if (m_binDisplay == PeakBins || 1901 if (m_binDisplay == PeakBins ||
1959 sr, 1919 sr,
1960 m_cache->getPhaseAt(s, q), 1920 m_cache->getPhaseAt(s, q),
1961 m_cache->getPhaseAt(s+1, q), 1921 m_cache->getPhaseAt(s+1, q),
1962 steady); 1922 steady);
1963 1923
1964 y0 = y1 = m_view->getYForFrequency 1924 y0 = y1 = v->getYForFrequency
1965 (f0, minFreq, maxFreq, logarithmic); 1925 (f0, minFreq, maxFreq, logarithmic);
1966 } 1926 }
1967 1927
1968 int y0i = int(y0 + 0.001); 1928 int y0i = int(y0 + 0.001);
1969 int y1i = int(y1); 1929 int y1i = int(y1);
2030 std::cerr << "SpectrogramLayer::paint() returning" << std::endl; 1990 std::cerr << "SpectrogramLayer::paint() returning" << std::endl;
2031 #endif 1991 #endif
2032 } 1992 }
2033 1993
2034 float 1994 float
2035 SpectrogramLayer::getYForFrequency(float frequency) const 1995 SpectrogramLayer::getYForFrequency(View *v, float frequency) const
2036 { 1996 {
2037 return m_view->getYForFrequency(frequency, 1997 return v->getYForFrequency(frequency,
2038 getEffectiveMinFrequency(), 1998 getEffectiveMinFrequency(),
2039 getEffectiveMaxFrequency(), 1999 getEffectiveMaxFrequency(),
2040 m_frequencyScale == LogFrequencyScale); 2000 m_frequencyScale == LogFrequencyScale);
2041 } 2001 }
2042 2002
2043 float 2003 float
2044 SpectrogramLayer::getFrequencyForY(int y) const 2004 SpectrogramLayer::getFrequencyForY(View *v, int y) const
2045 { 2005 {
2046 return m_view->getFrequencyForY(y, 2006 return v->getFrequencyForY(y,
2047 getEffectiveMinFrequency(), 2007 getEffectiveMinFrequency(),
2048 getEffectiveMaxFrequency(), 2008 getEffectiveMaxFrequency(),
2049 m_frequencyScale == LogFrequencyScale); 2009 m_frequencyScale == LogFrequencyScale);
2050 } 2010 }
2051 2011
2052 int 2012 int
2053 SpectrogramLayer::getCompletion() const 2013 SpectrogramLayer::getCompletion() const
2054 { 2014 {
2057 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl; 2017 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl;
2058 return completion; 2018 return completion;
2059 } 2019 }
2060 2020
2061 bool 2021 bool
2062 SpectrogramLayer::snapToFeatureFrame(int &frame, 2022 SpectrogramLayer::snapToFeatureFrame(View *v, int &frame,
2063 size_t &resolution, 2023 size_t &resolution,
2064 SnapType snap) const 2024 SnapType snap) const
2065 { 2025 {
2066 resolution = getWindowIncrement(); 2026 resolution = getWindowIncrement();
2067 int left = (frame / resolution) * resolution; 2027 int left = (frame / resolution) * resolution;
2079 2039
2080 return true; 2040 return true;
2081 } 2041 }
2082 2042
2083 QString 2043 QString
2084 SpectrogramLayer::getFeatureDescription(QPoint &pos) const 2044 SpectrogramLayer::getFeatureDescription(View *v, QPoint &pos) const
2085 { 2045 {
2086 int x = pos.x(); 2046 int x = pos.x();
2087 int y = pos.y(); 2047 int y = pos.y();
2088 2048
2089 if (!m_model || !m_model->isOK()) return ""; 2049 if (!m_model || !m_model->isOK()) return "";
2095 QString pitchMin, pitchMax; 2055 QString pitchMin, pitchMax;
2096 RealTime rtMin, rtMax; 2056 RealTime rtMin, rtMax;
2097 2057
2098 bool haveValues = false; 2058 bool haveValues = false;
2099 2059
2100 if (!getXBinSourceRange(x, rtMin, rtMax)) { 2060 if (!getXBinSourceRange(v, x, rtMin, rtMax)) {
2101 return ""; 2061 return "";
2102 } 2062 }
2103 if (getXYBinSourceRange(x, y, magMin, magMax, phaseMin, phaseMax)) { 2063 if (getXYBinSourceRange(v, x, y, magMin, magMax, phaseMin, phaseMax)) {
2104 haveValues = true; 2064 haveValues = true;
2105 } 2065 }
2106 2066
2107 QString adjFreqText = "", adjPitchText = ""; 2067 QString adjFreqText = "", adjPitchText = "";
2108 2068
2109 if (m_binDisplay == PeakFrequencies) { 2069 if (m_binDisplay == PeakFrequencies) {
2110 2070
2111 if (!getAdjustedYBinSourceRange(x, y, freqMin, freqMax, 2071 if (!getAdjustedYBinSourceRange(v, x, y, freqMin, freqMax,
2112 adjFreqMin, adjFreqMax)) { 2072 adjFreqMin, adjFreqMax)) {
2113 return ""; 2073 return "";
2114 } 2074 }
2115 2075
2116 if (adjFreqMin != adjFreqMax) { 2076 if (adjFreqMin != adjFreqMax) {
2130 adjPitchText = tr("Adjusted Pitch:\t%2\n").arg(pmin); 2090 adjPitchText = tr("Adjusted Pitch:\t%2\n").arg(pmin);
2131 } 2091 }
2132 2092
2133 } else { 2093 } else {
2134 2094
2135 if (!getYBinSourceRange(y, freqMin, freqMax)) return ""; 2095 if (!getYBinSourceRange(v, y, freqMin, freqMax)) return "";
2136 } 2096 }
2137 2097
2138 QString text; 2098 QString text;
2139 2099
2140 if (rtMin != rtMax) { 2100 if (rtMin != rtMax) {
2216 2176
2217 return cw; 2177 return cw;
2218 } 2178 }
2219 2179
2220 int 2180 int
2221 SpectrogramLayer::getVerticalScaleWidth(QPainter &paint) const 2181 SpectrogramLayer::getVerticalScaleWidth(View *v, QPainter &paint) const
2222 { 2182 {
2223 if (!m_model || !m_model->isOK()) return 0; 2183 if (!m_model || !m_model->isOK()) return 0;
2224 2184
2225 int cw = getColourScaleWidth(paint); 2185 int cw = getColourScaleWidth(paint);
2226 2186
2236 2196
2237 return cw + tickw + tw + 13; 2197 return cw + tickw + tw + 13;
2238 } 2198 }
2239 2199
2240 void 2200 void
2241 SpectrogramLayer::paintVerticalScale(QPainter &paint, QRect rect) const 2201 SpectrogramLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
2242 { 2202 {
2243 if (!m_model || !m_model->isOK()) { 2203 if (!m_model || !m_model->isOK()) {
2244 return; 2204 return;
2245 } 2205 }
2246 2206
2315 2275
2316 paint.drawLine(cw + 7, 0, cw + 7, h); 2276 paint.drawLine(cw + 7, 0, cw + 7, h);
2317 2277
2318 int bin = -1; 2278 int bin = -1;
2319 2279
2320 for (int y = 0; y < m_view->height(); ++y) { 2280 for (int y = 0; y < v->height(); ++y) {
2321 2281
2322 float q0, q1; 2282 float q0, q1;
2323 if (!getYBinRange(m_view->height() - y, q0, q1)) continue; 2283 if (!getYBinRange(v, v->height() - y, q0, q1)) continue;
2324 2284
2325 int vy; 2285 int vy;
2326 2286
2327 if (int(q0) > bin) { 2287 if (int(q0) > bin) {
2328 vy = y; 2288 vy = y;
2364 paint.setBrush(paint.pen().color()); 2324 paint.setBrush(paint.pen().color());
2365 2325
2366 for (int i = 0; i < 128; ++i) { 2326 for (int i = 0; i < 128; ++i) {
2367 2327
2368 float f = Pitch::getFrequencyForPitch(i); 2328 float f = Pitch::getFrequencyForPitch(i);
2369 int y = lrintf(m_view->getYForFrequency(f, minf, maxf, true)); 2329 int y = lrintf(v->getYForFrequency(f, minf, maxf, true));
2370 int n = (i % 12); 2330 int n = (i % 12);
2371 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { 2331 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) {
2372 // black notes 2332 // black notes
2373 paint.drawLine(w - pkw, y, w, y); 2333 paint.drawLine(w - pkw, y, w, y);
2374 int rh = ((py - y) / 4) * 2; 2334 int rh = ((py - y) / 4) * 2;