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