comparison layer/SpectrogramLayer.cpp @ 95:1b3996a86cfa

* Incremental refresh of spectrogram layer
author Chris Cannam
date Tue, 09 May 2006 16:18:59 +0000
parents 05c41701dc6c
children 095916d7ed4d
comparison
equal deleted inserted replaced
94:c7ade7ea3cfe 95:1b3996a86cfa
67 m_binDisplay(AllBins), 67 m_binDisplay(AllBins),
68 m_normalizeColumns(false), 68 m_normalizeColumns(false),
69 m_cache(0), 69 m_cache(0),
70 m_writeCache(0), 70 m_writeCache(0),
71 m_cacheInvalid(true), 71 m_cacheInvalid(true),
72 m_pixmapCache(0),
73 m_pixmapCacheInvalid(true),
74 m_fillThread(0), 72 m_fillThread(0),
75 m_updateTimer(0), 73 m_updateTimer(0),
76 m_candidateFillStartFrame(0), 74 m_candidateFillStartFrame(0),
77 m_lastFillExtent(0), 75 m_lastFillExtent(0),
78 m_exiting(false) 76 m_exiting(false)
517 setNormalizeColumns(value ? true : false); 515 setNormalizeColumns(value ? true : false);
518 } 516 }
519 } 517 }
520 518
521 void 519 void
520 SpectrogramLayer::invalidatePixmapCaches()
521 {
522 for (ViewPixmapCache::iterator i = m_pixmapCaches.begin();
523 i != m_pixmapCaches.end(); ++i) {
524 i->second.validArea = QRect();
525 }
526 }
527
528 void
529 SpectrogramLayer::invalidatePixmapCaches(size_t startFrame, size_t endFrame)
530 {
531 for (ViewPixmapCache::iterator i = m_pixmapCaches.begin();
532 i != m_pixmapCaches.end(); ++i) {
533 //!!! when are views removed from the map? on setLayerDormant?
534 const View *v = i->first;
535
536 if (startFrame < v->getEndFrame() && endFrame >= v->getStartFrame()) {
537 i->second.validArea = QRect();
538 }
539 }
540 }
541
542 void
522 SpectrogramLayer::setChannel(int ch) 543 SpectrogramLayer::setChannel(int ch)
523 { 544 {
524 if (m_channel == ch) return; 545 if (m_channel == ch) return;
525 546
526 m_mutex.lock(); 547 m_mutex.lock();
527 m_cacheInvalid = true; 548 m_cacheInvalid = true;
528 m_pixmapCacheInvalid = true; 549 invalidatePixmapCaches();
529 550
530 m_channel = ch; 551 m_channel = ch;
531 552
532 m_mutex.unlock(); 553 m_mutex.unlock();
533 554
547 { 568 {
548 if (m_windowSize == ws) return; 569 if (m_windowSize == ws) return;
549 570
550 m_mutex.lock(); 571 m_mutex.lock();
551 m_cacheInvalid = true; 572 m_cacheInvalid = true;
552 m_pixmapCacheInvalid = true; 573 invalidatePixmapCaches();
553 574
554 m_windowSize = ws; 575 m_windowSize = ws;
555 576
556 m_mutex.unlock(); 577 m_mutex.unlock();
557 578
571 { 592 {
572 if (m_windowOverlap == wi) return; 593 if (m_windowOverlap == wi) return;
573 594
574 m_mutex.lock(); 595 m_mutex.lock();
575 m_cacheInvalid = true; 596 m_cacheInvalid = true;
576 m_pixmapCacheInvalid = true; 597 invalidatePixmapCaches();
577 598
578 m_windowOverlap = wi; 599 m_windowOverlap = wi;
579 600
580 m_mutex.unlock(); 601 m_mutex.unlock();
581 602
595 { 616 {
596 if (m_windowType == w) return; 617 if (m_windowType == w) return;
597 618
598 m_mutex.lock(); 619 m_mutex.lock();
599 m_cacheInvalid = true; 620 m_cacheInvalid = true;
600 m_pixmapCacheInvalid = true; 621 invalidatePixmapCaches();
601 622
602 m_windowType = w; 623 m_windowType = w;
603 624
604 m_mutex.unlock(); 625 m_mutex.unlock();
605 626
621 << m_gain << ")" << std::endl; 642 << m_gain << ")" << std::endl;
622 643
623 if (m_gain == gain) return; 644 if (m_gain == gain) return;
624 645
625 m_mutex.lock(); 646 m_mutex.lock();
626 m_pixmapCacheInvalid = true; 647 invalidatePixmapCaches();
627 648
628 m_gain = gain; 649 m_gain = gain;
629 650
630 m_mutex.unlock(); 651 m_mutex.unlock();
631 652
644 SpectrogramLayer::setThreshold(float threshold) 665 SpectrogramLayer::setThreshold(float threshold)
645 { 666 {
646 if (m_threshold == threshold) return; 667 if (m_threshold == threshold) return;
647 668
648 m_mutex.lock(); 669 m_mutex.lock();
649 m_pixmapCacheInvalid = true; 670 invalidatePixmapCaches();
650 671
651 m_threshold = threshold; 672 m_threshold = threshold;
652 673
653 m_mutex.unlock(); 674 m_mutex.unlock();
654 675
667 SpectrogramLayer::setMinFrequency(size_t mf) 688 SpectrogramLayer::setMinFrequency(size_t mf)
668 { 689 {
669 if (m_minFrequency == mf) return; 690 if (m_minFrequency == mf) return;
670 691
671 m_mutex.lock(); 692 m_mutex.lock();
672 m_pixmapCacheInvalid = true; 693 invalidatePixmapCaches();
673 694
674 m_minFrequency = mf; 695 m_minFrequency = mf;
675 696
676 m_mutex.unlock(); 697 m_mutex.unlock();
677 698
688 SpectrogramLayer::setMaxFrequency(size_t mf) 709 SpectrogramLayer::setMaxFrequency(size_t mf)
689 { 710 {
690 if (m_maxFrequency == mf) return; 711 if (m_maxFrequency == mf) return;
691 712
692 m_mutex.lock(); 713 m_mutex.lock();
693 m_pixmapCacheInvalid = true; 714 invalidatePixmapCaches();
694 715
695 m_maxFrequency = mf; 716 m_maxFrequency = mf;
696 717
697 m_mutex.unlock(); 718 m_mutex.unlock();
698 719
707 728
708 void 729 void
709 SpectrogramLayer::setColourRotation(int r) 730 SpectrogramLayer::setColourRotation(int r)
710 { 731 {
711 m_mutex.lock(); 732 m_mutex.lock();
712 m_pixmapCacheInvalid = true; 733 invalidatePixmapCaches();
713 734
714 if (r < 0) r = 0; 735 if (r < 0) r = 0;
715 if (r > 256) r = 256; 736 if (r > 256) r = 256;
716 int distance = r - m_colourRotation; 737 int distance = r - m_colourRotation;
717 738
729 SpectrogramLayer::setColourScale(ColourScale colourScale) 750 SpectrogramLayer::setColourScale(ColourScale colourScale)
730 { 751 {
731 if (m_colourScale == colourScale) return; 752 if (m_colourScale == colourScale) return;
732 753
733 m_mutex.lock(); 754 m_mutex.lock();
734 m_pixmapCacheInvalid = true; 755 invalidatePixmapCaches();
735 756
736 m_colourScale = colourScale; 757 m_colourScale = colourScale;
737 758
738 m_mutex.unlock(); 759 m_mutex.unlock();
739 fillCache(); 760 fillCache();
751 SpectrogramLayer::setColourScheme(ColourScheme scheme) 772 SpectrogramLayer::setColourScheme(ColourScheme scheme)
752 { 773 {
753 if (m_colourScheme == scheme) return; 774 if (m_colourScheme == scheme) return;
754 775
755 m_mutex.lock(); 776 m_mutex.lock();
756 m_pixmapCacheInvalid = true; 777 invalidatePixmapCaches();
757 778
758 m_colourScheme = scheme; 779 m_colourScheme = scheme;
759 setColourmap(); 780 setColourmap();
760 781
761 m_mutex.unlock(); 782 m_mutex.unlock();
774 { 795 {
775 if (m_frequencyScale == frequencyScale) return; 796 if (m_frequencyScale == frequencyScale) return;
776 797
777 m_mutex.lock(); 798 m_mutex.lock();
778 799
779 m_pixmapCacheInvalid = true; 800 invalidatePixmapCaches();
780 801
781 m_frequencyScale = frequencyScale; 802 m_frequencyScale = frequencyScale;
782 803
783 m_mutex.unlock(); 804 m_mutex.unlock();
784 805
796 { 817 {
797 if (m_binDisplay == binDisplay) return; 818 if (m_binDisplay == binDisplay) return;
798 819
799 m_mutex.lock(); 820 m_mutex.lock();
800 821
801 m_pixmapCacheInvalid = true; 822 invalidatePixmapCaches();
802 823
803 m_binDisplay = binDisplay; 824 m_binDisplay = binDisplay;
804 825
805 m_mutex.unlock(); 826 m_mutex.unlock();
806 827
819 SpectrogramLayer::setNormalizeColumns(bool n) 840 SpectrogramLayer::setNormalizeColumns(bool n)
820 { 841 {
821 if (m_normalizeColumns == n) return; 842 if (m_normalizeColumns == n) return;
822 m_mutex.lock(); 843 m_mutex.lock();
823 844
824 m_pixmapCacheInvalid = true; 845 invalidatePixmapCaches();
825 m_normalizeColumns = n; 846 m_normalizeColumns = n;
826 m_mutex.unlock(); 847 m_mutex.unlock();
827 848
828 fillCache(); 849 fillCache();
829 emit layerParametersChanged(); 850 emit layerParametersChanged();
848 869
849 // delete m_cache; 870 // delete m_cache;
850 // m_cache = 0; 871 // m_cache = 0;
851 872
852 m_cacheInvalid = true; 873 m_cacheInvalid = true;
853 m_pixmapCacheInvalid = true; 874 invalidatePixmapCaches();
854 delete m_pixmapCache; 875 m_pixmapCaches.erase(v);
855 m_pixmapCache = 0;
856 876
857 } else { 877 } else {
858 878
859 m_dormancy[v] = false; 879 m_dormancy[v] = false;
860 } 880 }
862 882
863 void 883 void
864 SpectrogramLayer::cacheInvalid() 884 SpectrogramLayer::cacheInvalid()
865 { 885 {
866 m_cacheInvalid = true; 886 m_cacheInvalid = true;
867 m_pixmapCacheInvalid = true; 887 invalidatePixmapCaches();
868 fillCache(); 888 fillCache();
869 } 889 }
870 890
871 void 891 void
872 SpectrogramLayer::cacheInvalid(size_t, size_t) 892 SpectrogramLayer::cacheInvalid(size_t, size_t)
910 if (fillExtent >= m_lastFillExtent) { 930 if (fillExtent >= m_lastFillExtent) {
911 if (fillExtent >= m_model->getEndFrame() && m_lastFillExtent > 0) { 931 if (fillExtent >= m_model->getEndFrame() && m_lastFillExtent > 0) {
912 #ifdef DEBUG_SPECTROGRAM_REPAINT 932 #ifdef DEBUG_SPECTROGRAM_REPAINT
913 std::cerr << "complete!" << std::endl; 933 std::cerr << "complete!" << std::endl;
914 #endif 934 #endif
915 m_pixmapCacheInvalid = true; 935 invalidatePixmapCaches();
916 emit modelChanged(); 936 emit modelChanged();
917 delete m_updateTimer; 937 delete m_updateTimer;
918 m_updateTimer = 0; 938 m_updateTimer = 0;
919 m_lastFillExtent = 0; 939 m_lastFillExtent = 0;
920 } else if (fillExtent > m_lastFillExtent) { 940 } else if (fillExtent > m_lastFillExtent) {
921 #ifdef DEBUG_SPECTROGRAM_REPAINT 941 #ifdef DEBUG_SPECTROGRAM_REPAINT
922 std::cerr << "SpectrogramLayer: emitting modelChanged(" 942 std::cerr << "SpectrogramLayer: emitting modelChanged("
923 << m_lastFillExtent << "," << fillExtent << ")" << std::endl; 943 << m_lastFillExtent << "," << fillExtent << ")" << std::endl;
924 #endif 944 #endif
925 m_pixmapCacheInvalid = true; 945 invalidatePixmapCaches(m_lastFillExtent, fillExtent);
926 emit modelChanged(m_lastFillExtent, fillExtent); 946 emit modelChanged(m_lastFillExtent, fillExtent);
927 m_lastFillExtent = fillExtent; 947 m_lastFillExtent = fillExtent;
928 } 948 }
929 } else { 949 } else {
930 // if (v) { 950 // if (v) {
932 //!!! if (v->getStartFrame() > 0) sf = v->getStartFrame(); 952 //!!! if (v->getStartFrame() > 0) sf = v->getStartFrame();
933 #ifdef DEBUG_SPECTROGRAM_REPAINT 953 #ifdef DEBUG_SPECTROGRAM_REPAINT
934 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" 954 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged("
935 << sf << "," << m_model->getEndFrame() << ")" << std::endl; 955 << sf << "," << m_model->getEndFrame() << ")" << std::endl;
936 #endif 956 #endif
937 m_pixmapCacheInvalid = true; 957 invalidatePixmapCaches();
938 emit modelChanged(sf, m_model->getEndFrame()); 958 emit modelChanged(sf, m_model->getEndFrame());
939 // } 959 // }
940 m_lastFillExtent = fillExtent; 960 m_lastFillExtent = fillExtent;
941 } 961 }
942 } 962 }
1692 v->setLightBackground(false); 1712 v->setLightBackground(false);
1693 } 1713 }
1694 1714
1695 // Profiler profiler("SpectrogramLayer::paint", true); 1715 // Profiler profiler("SpectrogramLayer::paint", true);
1696 #ifdef DEBUG_SPECTROGRAM_REPAINT 1716 #ifdef DEBUG_SPECTROGRAM_REPAINT
1697 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; 1717 std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << std::endl;
1718
1719 std::cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << std::endl;
1698 #endif 1720 #endif
1699 1721
1700 long sf = v->getStartFrame(); 1722 long sf = v->getStartFrame();
1701 if (sf < 0) m_candidateFillStartFrame = 0; 1723 if (sf < 0) m_candidateFillStartFrame = 0;
1702 else m_candidateFillStartFrame = sf; 1724 else m_candidateFillStartFrame = sf;
1703 1725
1704 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1726 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1714 // and accountable for when determining whether we need the cache 1736 // and accountable for when determining whether we need the cache
1715 // in the cache-fill thread above. 1737 // in the cache-fill thread above.
1716 m_dormancy[v] = false; 1738 m_dormancy[v] = false;
1717 1739
1718 #ifdef DEBUG_SPECTROGRAM_REPAINT 1740 #ifdef DEBUG_SPECTROGRAM_REPAINT
1719 std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl; 1741 // std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl;
1720 #endif 1742 #endif
1721 1743
1722 m_mutex.lock(); 1744 m_mutex.lock();
1723 1745
1724 #ifdef DEBUG_SPECTROGRAM_REPAINT 1746 #ifdef DEBUG_SPECTROGRAM_REPAINT
1725 std::cerr << "SpectrogramLayer::paint(): locked" << std::endl; 1747 // std::cerr << "SpectrogramLayer::paint(): locked" << std::endl;
1726 #endif 1748 #endif
1727 1749
1728 if (m_cacheInvalid) { // lock the mutex before checking this 1750 if (m_cacheInvalid) { // lock the mutex before checking this
1729 m_mutex.unlock(); 1751 m_mutex.unlock();
1730 #ifdef DEBUG_SPECTROGRAM_REPAINT 1752 #ifdef DEBUG_SPECTROGRAM_REPAINT
1731 std::cerr << "SpectrogramLayer::paint(): Cache invalid, returning" << std::endl; 1753 std::cerr << "SpectrogramLayer::paint(): Cache invalid, returning" << std::endl;
1732 #endif 1754 #endif
1733 return; 1755 return;
1734 } 1756 }
1735 1757
1758 PixmapCache &cache = m_pixmapCaches[v];
1759
1760 #ifdef DEBUG_SPECTROGRAM_REPAINT
1761 std::cerr << "SpectrogramLayer::paint(): pixmap cache valid area " << cache.validArea.x() << ", " << cache.validArea.y() << ", " << cache.validArea.width() << "x" << cache.validArea.height() << std::endl;
1762 #endif
1763
1736 bool stillCacheing = (m_updateTimer != 0); 1764 bool stillCacheing = (m_updateTimer != 0);
1737 1765
1738 #ifdef DEBUG_SPECTROGRAM_REPAINT 1766 #ifdef DEBUG_SPECTROGRAM_REPAINT
1739 std::cerr << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << std::endl; 1767 std::cerr << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << std::endl;
1740 #endif 1768 #endif
1747 int y0 = 0; 1775 int y0 = 0;
1748 int y1 = v->height(); 1776 int y1 = v->height();
1749 1777
1750 bool recreateWholePixmapCache = true; 1778 bool recreateWholePixmapCache = true;
1751 1779
1752 // if (stillCacheing) { 1780 x0 = rect.left();
1753 x0 = rect.left(); 1781 x1 = rect.right() + 1;
1754 x1 = rect.right() + 1; 1782 y0 = rect.top();
1755 y0 = rect.top(); 1783 y1 = rect.bottom() + 1;
1756 y1 = rect.bottom() + 1; 1784
1757 // } 1785 if (cache.validArea.width() > 0) {
1758 1786
1759 if (!m_pixmapCacheInvalid) { 1787 if (int(cache.zoomLevel) == zoomLevel &&
1760 1788 cache.pixmap.width() == v->width() &&
1761 //!!! This cache may have been obsoleted entirely by the 1789 cache.pixmap.height() == v->height()) {
1762 //scrolling cache in View. Perhaps experiment with 1790
1763 //removing it and see if it makes things even quicker (or else 1791 if (v->getXForFrame(cache.startFrame) ==
1764 //make it optional) 1792 v->getXForFrame(startFrame) &&
1765 1793 cache.validArea.x() <= x0 &&
1766 if (int(m_pixmapCacheZoomLevel) == zoomLevel && 1794 cache.validArea.x() + cache.validArea.width() >= x1) {
1767 m_pixmapCache->width() == v->width() &&
1768 m_pixmapCache->height() == v->height()) {
1769
1770 if (v->getXForFrame(m_pixmapCacheStartFrame) ==
1771 v->getXForFrame(startFrame)) {
1772 1795
1773 #ifdef DEBUG_SPECTROGRAM_REPAINT 1796 #ifdef DEBUG_SPECTROGRAM_REPAINT
1774 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl; 1797 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl;
1775 #endif 1798 #endif
1776 1799
1777 m_mutex.unlock(); 1800 m_mutex.unlock();
1778 paint.drawPixmap(rect, *m_pixmapCache, rect); 1801 paint.drawPixmap(rect, cache.pixmap, rect);
1779 return; 1802 return;
1780 1803
1781 } else { 1804 } else {
1782 1805
1783 #ifdef DEBUG_SPECTROGRAM_REPAINT 1806 #ifdef DEBUG_SPECTROGRAM_REPAINT
1784 std::cerr << "SpectrogramLayer: pixmap cache partially OK" << std::endl; 1807 std::cerr << "SpectrogramLayer: pixmap cache partially OK" << std::endl;
1785 #endif 1808 #endif
1786 1809
1787 recreateWholePixmapCache = false; 1810 recreateWholePixmapCache = false;
1788 1811
1789 int dx = v->getXForFrame(m_pixmapCacheStartFrame) - 1812 int dx = v->getXForFrame(cache.startFrame) -
1790 v->getXForFrame(startFrame); 1813 v->getXForFrame(startFrame);
1791 1814
1792 #ifdef DEBUG_SPECTROGRAM_REPAINT 1815 #ifdef DEBUG_SPECTROGRAM_REPAINT
1793 std::cerr << "SpectrogramLayer: dx = " << dx << " (pixmap cache " << m_pixmapCache->width() << "x" << m_pixmapCache->height() << ")" << std::endl; 1816 std::cerr << "SpectrogramLayer: dx = " << dx << " (pixmap cache " << cache.pixmap.width() << "x" << cache.pixmap.height() << ")" << std::endl;
1794 #endif 1817 #endif
1795 1818
1796 if (dx > -m_pixmapCache->width() && dx < m_pixmapCache->width()) { 1819 if (dx != 0 &&
1820 dx > -cache.pixmap.width() &&
1821 dx < cache.pixmap.width()) {
1797 1822
1798 #if defined(Q_WS_WIN32) || defined(Q_WS_MAC) 1823 #if defined(Q_WS_WIN32) || defined(Q_WS_MAC)
1799 // Copying a pixmap to itself doesn't work 1824 // Copying a pixmap to itself doesn't work
1800 // properly on Windows or Mac (it only works when 1825 // properly on Windows or Mac (it only works when
1801 // moving in one direction). 1826 // moving in one direction).
1802 1827
1803 //!!! Need a utility function for this 1828 //!!! Need a utility function for this
1804 1829
1805 static QPixmap *tmpPixmap = 0; 1830 static QPixmap *tmpPixmap = 0;
1806 if (!tmpPixmap || 1831 if (!tmpPixmap ||
1807 tmpPixmap->width() != m_pixmapCache->width() || 1832 tmpPixmap->width() != cache.pixmap.width() ||
1808 tmpPixmap->height() != m_pixmapCache->height()) { 1833 tmpPixmap->height() != cache.pixmap.height()) {
1809 delete tmpPixmap; 1834 delete tmpPixmap;
1810 tmpPixmap = new QPixmap(m_pixmapCache->width(), 1835 tmpPixmap = new QPixmap(cache.pixmap.width(),
1811 m_pixmapCache->height()); 1836 cache.pixmap.height());
1812 } 1837 }
1813 QPainter cachePainter; 1838 QPainter cachePainter;
1814 cachePainter.begin(tmpPixmap); 1839 cachePainter.begin(tmpPixmap);
1815 cachePainter.drawPixmap(0, 0, *m_pixmapCache); 1840 cachePainter.drawPixmap(0, 0, cache.pixmap);
1816 cachePainter.end(); 1841 cachePainter.end();
1817 cachePainter.begin(m_pixmapCache); 1842 cachePainter.begin(&cache.pixmap);
1818 cachePainter.drawPixmap(dx, 0, *tmpPixmap); 1843 cachePainter.drawPixmap(dx, 0, *tmpPixmap);
1819 cachePainter.end(); 1844 cachePainter.end();
1820 #else 1845 #else
1821 QPainter cachePainter(m_pixmapCache); 1846 QPainter cachePainter(&cache.pixmap);
1822 cachePainter.drawPixmap(dx, 0, *m_pixmapCache); 1847 cachePainter.drawPixmap(dx, 0, cache.pixmap);
1823 cachePainter.end(); 1848 cachePainter.end();
1824 #endif 1849 #endif
1825 1850
1826 paint.drawPixmap(rect, *m_pixmapCache, rect); 1851 int px = cache.validArea.x();
1852 int pw = cache.validArea.width();
1827 1853
1828 if (dx < 0) { 1854 if (dx < 0) {
1829 x0 = m_pixmapCache->width() + dx; 1855 x0 = cache.pixmap.width() + dx;
1830 x1 = m_pixmapCache->width(); 1856 x1 = cache.pixmap.width();
1857 px += dx;
1858 if (px < 0) {
1859 pw += px;
1860 px = 0;
1861 if (pw < 0) pw = 0;
1862 }
1831 } else { 1863 } else {
1832 x0 = 0; 1864 x0 = 0;
1833 x1 = dx; 1865 x1 = dx;
1866 px += dx;
1867 if (px + pw > cache.pixmap.width()) {
1868 pw = int(cache.pixmap.width()) - px;
1869 if (pw < 0) pw = 0;
1870 }
1834 } 1871 }
1872
1873 cache.validArea =
1874 QRect(px, cache.validArea.y(),
1875 pw, cache.validArea.height());
1876
1877 paint.drawPixmap(rect & cache.validArea,
1878 cache.pixmap,
1879 rect & cache.validArea);
1835 } 1880 }
1836 } 1881 }
1837 } else { 1882 } else {
1838 #ifdef DEBUG_SPECTROGRAM_REPAINT 1883 #ifdef DEBUG_SPECTROGRAM_REPAINT
1839 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl; 1884 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl;
1840 #endif 1885 #endif
1841 } 1886 cache.validArea = QRect();
1842 } 1887 }
1888 }
1889
1843 /* 1890 /*
1844 if (stillCacheing) { 1891 if (stillCacheing) {
1845 x0 = rect.left(); 1892 x0 = rect.left();
1846 x1 = rect.right() + 1; 1893 x1 = rect.right() + 1;
1847 y0 = rect.top(); 1894 y0 = rect.top();
1848 y1 = rect.bottom() + 1; 1895 y1 = rect.bottom() + 1;
1849 } 1896 }
1850 */ 1897 */
1898
1899 if (recreateWholePixmapCache) {
1900
1901 x0 = 0;
1902 x1 = v->width();
1903 // cache.validArea = QRect(x0, 0, x1, v->height());
1904 }
1905
1906 if (1) {//!!!
1907
1908 int paintBlockWidth = (500000 / zoomLevel);
1909 if (paintBlockWidth < 20) paintBlockWidth = 20;
1910
1911 if (cache.validArea.width() > 0) {
1912
1913 int vx0 = 0, vx1 = 0;
1914 vx0 = cache.validArea.x();
1915 vx1 = cache.validArea.x() + cache.validArea.width();
1916
1917 #ifdef DEBUG_SPECTROGRAM_REPAINT
1918 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl;
1919 #endif
1920 if (x0 < vx0) {
1921 if (x0 + paintBlockWidth < vx0) {
1922 x0 = vx0 - paintBlockWidth;
1923 } else {
1924 x0 = 0;
1925 }
1926 } else if (x0 > vx1) {
1927 x0 = vx1;
1928 }
1929
1930 if (x1 < vx0) {
1931 x1 = vx0;
1932 } else if (x1 > vx1) {
1933 if (vx1 + paintBlockWidth < x1) {
1934 x1 = vx1 + paintBlockWidth;
1935 } else {
1936 x1 = v->width();
1937 }
1938 }
1939
1940 cache.validArea = QRect
1941 (std::min(vx0, x0), cache.validArea.y(),
1942 std::max(vx1 - std::min(vx0, x0),
1943 x1 - std::min(vx0, x0)),
1944 cache.validArea.height());
1945
1946 } else {
1947 if (x1 > x0 + paintBlockWidth) {
1948 x1 = x0 + paintBlockWidth;
1949 }
1950 cache.validArea = QRect(x0, 0, x1 - x0, v->height());
1951 }
1952 }
1953
1851 int w = x1 - x0; 1954 int w = x1 - x0;
1852 int h = y1 - y0; 1955 int h = y1 - y0;
1853 1956
1854 // std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl; 1957 #ifdef DEBUG_SPECTROGRAM_REPAINT
1855 1958 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl;
1856 QImage scaled(w, h, QImage::Format_RGB32); 1959 #endif
1857 scaled.fill(m_colourMap.getColour(0).rgb()); 1960
1961 if (m_drawBuffer.width() < w || m_drawBuffer.height() < h) {
1962 m_drawBuffer = QImage(w, h, QImage::Format_RGB32);
1963 }
1964
1965 // if (m_binDisplay == PeakFrequencies) {
1966 m_drawBuffer.fill(m_colourMap.getColour(0).rgb());
1967 // }
1858 1968
1859 int sr = m_model->getSampleRate(); 1969 int sr = m_model->getSampleRate();
1860 1970
1861 size_t bins = m_windowSize / 2; 1971 size_t bins = m_windowSize / 2;
1862 if (m_maxFrequency > 0) { 1972 if (m_maxFrequency > 0) {
1887 for (size_t q = minbin; q <= bins; ++q) { 1997 for (size_t q = minbin; q <= bins; ++q) {
1888 float f0 = (float(q) * sr) / m_windowSize; 1998 float f0 = (float(q) * sr) / m_windowSize;
1889 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); 1999 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1890 } 2000 }
1891 2001
2002 m_mutex.lock();
2003
1892 for (int x = 0; x < w; ++x) { 2004 for (int x = 0; x < w; ++x) {
1893 2005
1894 m_mutex.lock(); 2006 if (x % 10 == 0) {
1895 if (m_cacheInvalid) { 2007 m_mutex.unlock();
1896 m_mutex.unlock(); 2008 m_mutex.lock();
1897 break; 2009 if (m_cacheInvalid) {
1898 } 2010 break;
2011 }
2012 }
1899 2013
1900 for (int y = 0; y < h; ++y) { 2014 for (int y = 0; y < h; ++y) {
1901 ymag[y] = 0.0; 2015 ymag[y] = 0.0;
1902 ydiv[y] = 0.0; 2016 ydiv[y] = 0.0;
1903 } 2017 }
1904 2018
1905 float s0 = 0, s1 = 0; 2019 float s0 = 0, s1 = 0;
1906 2020
1907 if (!getXBinRange(v, x0 + x, s0, s1)) { 2021 if (!getXBinRange(v, x0 + x, s0, s1)) {
1908 assert(x <= scaled.width()); 2022 assert(x <= m_drawBuffer.width());
1909 m_mutex.unlock();
1910 continue; 2023 continue;
1911 } 2024 }
1912 2025
1913 int s0i = int(s0 + 0.001); 2026 int s0i = int(s0 + 0.001);
1914 int s1i = int(s1); 2027 int s1i = int(s1);
1915 2028
1916 if (s1i >= m_cache->getWidth()) { 2029 if (s1i >= m_cache->getWidth()) {
1917 if (s0i >= m_cache->getWidth()) { 2030 if (s0i >= m_cache->getWidth()) {
1918 m_mutex.unlock();
1919 continue; 2031 continue;
1920 } else { 2032 } else {
1921 s1i = s0i; 2033 s1i = s0i;
1922 } 2034 }
1923 } 2035 }
1991 unsigned char pixel = 0; 2103 unsigned char pixel = 0;
1992 2104
1993 float avg = ymag[y] / ydiv[y]; 2105 float avg = ymag[y] / ydiv[y];
1994 pixel = getDisplayValue(avg); 2106 pixel = getDisplayValue(avg);
1995 2107
1996 assert(x <= scaled.width()); 2108 assert(x <= m_drawBuffer.width());
1997 QColor c = m_colourMap.getColour(pixel); 2109 QColor c = m_colourMap.getColour(pixel);
1998 scaled.setPixel(x, y, 2110 m_drawBuffer.setPixel(x, y,
1999 qRgb(c.red(), c.green(), c.blue())); 2111 qRgb(c.red(), c.green(), c.blue()));
2000 } 2112 }
2001 } 2113 }
2002 2114 }
2003 m_mutex.unlock(); 2115
2004 } 2116 m_mutex.unlock();
2005 2117
2006 paint.drawImage(x0, y0, scaled); 2118 paint.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h);
2007 2119
2008 if (recreateWholePixmapCache) { 2120 if (recreateWholePixmapCache) {
2009 delete m_pixmapCache; 2121 cache.pixmap = QPixmap(v->width(), v->height());
2010 m_pixmapCache = new QPixmap(w, h); 2122 }
2011 } 2123
2012 2124 QPainter cachePainter(&cache.pixmap);
2013 QPainter cachePainter(m_pixmapCache); 2125 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h);
2014 cachePainter.drawImage(x0, y0, scaled);
2015 cachePainter.end(); 2126 cachePainter.end();
2016 2127
2017 m_pixmapCacheInvalid = false; 2128 // m_pixmapCacheInvalid = false;
2018 m_pixmapCacheStartFrame = startFrame; 2129 cache.startFrame = startFrame;
2019 m_pixmapCacheZoomLevel = zoomLevel; 2130 cache.zoomLevel = zoomLevel;
2131
2132 if (cache.validArea.x() > 0) {
2133 #ifdef DEBUG_SPECTROGRAM_REPAINT
2134 std::cerr << "SpectrogramLayer::paint() updating left" << std::endl;
2135 #endif
2136 v->update(0, 0, cache.validArea.x(), v->height());
2137 }
2138
2139 if (cache.validArea.x() + cache.validArea.width() <
2140 cache.pixmap.width()) {
2141 #ifdef DEBUG_SPECTROGRAM_REPAINT
2142 std::cerr << "SpectrogramLayer::paint() updating right ("
2143 << cache.validArea.x() + cache.validArea.width()
2144 << ", "
2145 << cache.pixmap.width() - (cache.validArea.x() +
2146 cache.validArea.width())
2147 << ")" << std::endl;
2148 #endif
2149 v->update(cache.validArea.x() + cache.validArea.width(),
2150 0,
2151 cache.pixmap.width() - (cache.validArea.x() +
2152 cache.validArea.width()),
2153 v->height());
2154 }
2020 2155
2021 #ifdef DEBUG_SPECTROGRAM_REPAINT 2156 #ifdef DEBUG_SPECTROGRAM_REPAINT
2022 std::cerr << "SpectrogramLayer::paint() returning" << std::endl; 2157 std::cerr << "SpectrogramLayer::paint() returning" << std::endl;
2023 #endif 2158 #endif
2024 } 2159 }