Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 706:97ea68f62c1f imaf_enc
Merge from default branch
author | Chris Cannam |
---|---|
date | Thu, 05 Dec 2013 09:47:02 +0000 |
parents | 8072264dc61f |
children | 67e6d518ac27 |
comparison
equal
deleted
inserted
replaced
678:26c5f7fd4807 | 706:97ea68f62c1f |
---|---|
25 #include "base/LogRange.h" | 25 #include "base/LogRange.h" |
26 #include "widgets/CommandHistory.h" | 26 #include "widgets/CommandHistory.h" |
27 #include "ColourMapper.h" | 27 #include "ColourMapper.h" |
28 #include "ImageRegionFinder.h" | 28 #include "ImageRegionFinder.h" |
29 #include "data/model/Dense3DModelPeakCache.h" | 29 #include "data/model/Dense3DModelPeakCache.h" |
30 #include "PianoScale.h" | |
30 | 31 |
31 #include <QPainter> | 32 #include <QPainter> |
32 #include <QImage> | 33 #include <QImage> |
33 #include <QPixmap> | 34 #include <QPixmap> |
34 #include <QRect> | 35 #include <QRect> |
38 #include <QMouseEvent> | 39 #include <QMouseEvent> |
39 #include <QTextStream> | 40 #include <QTextStream> |
40 | 41 |
41 #include <iostream> | 42 #include <iostream> |
42 | 43 |
43 using std::cerr; | 44 |
44 using std::endl; | 45 |
45 #include <cassert> | 46 #include <cassert> |
46 #include <cmath> | 47 #include <cmath> |
47 | 48 |
48 #ifndef __GNUC__ | 49 #ifndef __GNUC__ |
49 #include <alloca.h> | 50 #include <alloca.h> |
125 } | 126 } |
126 | 127 |
127 void | 128 void |
128 SpectrogramLayer::setModel(const DenseTimeValueModel *model) | 129 SpectrogramLayer::setModel(const DenseTimeValueModel *model) |
129 { | 130 { |
130 // std::cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << std::endl; | 131 // cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << endl; |
131 | 132 |
132 if (model == m_model) return; | 133 if (model == m_model) return; |
133 | 134 |
134 m_model = model; | 135 m_model = model; |
135 invalidateFFTModels(); | 136 invalidateFFTModels(); |
582 SVDEBUG << "SpectrogramLayer::invalidateImageCaches(" | 583 SVDEBUG << "SpectrogramLayer::invalidateImageCaches(" |
583 << startFrame << ", " << endFrame << "): view range is " | 584 << startFrame << ", " << endFrame << "): view range is " |
584 << v->getStartFrame() << ", " << v->getEndFrame() | 585 << v->getStartFrame() << ", " << v->getEndFrame() |
585 << endl; | 586 << endl; |
586 | 587 |
587 std::cerr << "Valid area was: " << i->second.validArea.x() << ", " | 588 cerr << "Valid area was: " << i->second.validArea.x() << ", " |
588 << i->second.validArea.y() << " " | 589 << i->second.validArea.y() << " " |
589 << i->second.validArea.width() << "x" | 590 << i->second.validArea.width() << "x" |
590 << i->second.validArea.height() << std::endl; | 591 << i->second.validArea.height() << endl; |
591 #endif | 592 #endif |
592 | 593 |
593 if (long(startFrame) > v->getStartFrame()) { | 594 if (long(startFrame) > v->getStartFrame()) { |
594 if (startFrame >= v->getEndFrame()) { | 595 if (startFrame >= v->getEndFrame()) { |
595 #ifdef DEBUG_SPECTROGRAM_REPAINT | 596 #ifdef DEBUG_SPECTROGRAM_REPAINT |
596 std::cerr << "Modified start frame is off right of view" << std::endl; | 597 cerr << "Modified start frame is off right of view" << endl; |
597 #endif | 598 #endif |
598 return; | 599 return; |
599 } | 600 } |
600 int x = v->getXForFrame(startFrame); | 601 int x = v->getXForFrame(startFrame); |
601 #ifdef DEBUG_SPECTROGRAM_REPAINT | 602 #ifdef DEBUG_SPECTROGRAM_REPAINT |
608 i->second.validArea = QRect(); | 609 i->second.validArea = QRect(); |
609 } | 610 } |
610 } else { | 611 } else { |
611 if (long(endFrame) < v->getStartFrame()) { | 612 if (long(endFrame) < v->getStartFrame()) { |
612 #ifdef DEBUG_SPECTROGRAM_REPAINT | 613 #ifdef DEBUG_SPECTROGRAM_REPAINT |
613 std::cerr << "Modified end frame is off left of view" << std::endl; | 614 cerr << "Modified end frame is off left of view" << endl; |
614 #endif | 615 #endif |
615 return; | 616 return; |
616 } | 617 } |
617 int x = v->getXForFrame(endFrame); | 618 int x = v->getXForFrame(endFrame); |
618 #ifdef DEBUG_SPECTROGRAM_REPAINT | 619 #ifdef DEBUG_SPECTROGRAM_REPAINT |
626 i->second.validArea = QRect(); | 627 i->second.validArea = QRect(); |
627 } | 628 } |
628 } | 629 } |
629 | 630 |
630 #ifdef DEBUG_SPECTROGRAM_REPAINT | 631 #ifdef DEBUG_SPECTROGRAM_REPAINT |
631 std::cerr << "Valid area is now: " << i->second.validArea.x() << ", " | 632 cerr << "Valid area is now: " << i->second.validArea.x() << ", " |
632 << i->second.validArea.y() << " " | 633 << i->second.validArea.y() << " " |
633 << i->second.validArea.width() << "x" | 634 << i->second.validArea.width() << "x" |
634 << i->second.validArea.height() << std::endl; | 635 << i->second.validArea.height() << endl; |
635 #endif | 636 #endif |
636 } | 637 } |
637 } | 638 } |
638 | 639 |
639 void | 640 void |
1065 #endif | 1066 #endif |
1066 | 1067 |
1067 if (fill >= lastFill) { | 1068 if (fill >= lastFill) { |
1068 if (fill >= m_model->getEndFrame() && lastFill > 0) { | 1069 if (fill >= m_model->getEndFrame() && lastFill > 0) { |
1069 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1070 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1070 std::cerr << "complete!" << std::endl; | 1071 cerr << "complete!" << endl; |
1071 #endif | 1072 #endif |
1072 invalidateImageCaches(); | 1073 invalidateImageCaches(); |
1073 i->second.second = -1; | 1074 i->second.second = -1; |
1074 emit modelChanged(); | 1075 emit modelChanged(); |
1075 | 1076 |
1076 } else if (fill > lastFill) { | 1077 } else if (fill > lastFill) { |
1077 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1078 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1078 std::cerr << "SpectrogramLayer: emitting modelChanged(" | 1079 cerr << "SpectrogramLayer: emitting modelChanged(" |
1079 << lastFill << "," << fill << ")" << std::endl; | 1080 << lastFill << "," << fill << ")" << endl; |
1080 #endif | 1081 #endif |
1081 invalidateImageCaches(lastFill, fill); | 1082 invalidateImageCaches(lastFill, fill); |
1082 i->second.second = fill; | 1083 i->second.second = fill; |
1083 emit modelChanged(lastFill, fill); | 1084 emit modelChanged(lastFill, fill); |
1084 } | 1085 } |
1085 } else { | 1086 } else { |
1086 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1087 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1087 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" | 1088 cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" |
1088 << m_model->getStartFrame() << "," << m_model->getEndFrame() << ")" << std::endl; | 1089 << m_model->getStartFrame() << "," << m_model->getEndFrame() << ")" << endl; |
1089 #endif | 1090 #endif |
1090 invalidateImageCaches(); | 1091 invalidateImageCaches(); |
1091 i->second.second = fill; | 1092 i->second.second = fill; |
1092 emit modelChanged(m_model->getStartFrame(), m_model->getEndFrame()); | 1093 emit modelChanged(m_model->getStartFrame(), m_model->getEndFrame()); |
1093 } | 1094 } |
1098 } | 1099 } |
1099 } | 1100 } |
1100 | 1101 |
1101 if (allDone) { | 1102 if (allDone) { |
1102 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1103 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1103 std::cerr << "SpectrogramLayer: all complete!" << std::endl; | 1104 cerr << "SpectrogramLayer: all complete!" << endl; |
1104 #endif | 1105 #endif |
1105 delete m_updateTimer; | 1106 delete m_updateTimer; |
1106 m_updateTimer = 0; | 1107 m_updateTimer = 0; |
1107 } | 1108 } |
1108 } | 1109 } |
1672 return 0; | 1673 return 0; |
1673 } | 1674 } |
1674 | 1675 |
1675 if (!m_sliceableModel) { | 1676 if (!m_sliceableModel) { |
1676 #ifdef DEBUG_SPECTROGRAM | 1677 #ifdef DEBUG_SPECTROGRAM |
1677 std::cerr << "SpectrogramLayer: emitting sliceableModelReplaced(0, " << model << ")" << std::endl; | 1678 cerr << "SpectrogramLayer: emitting sliceableModelReplaced(0, " << model << ")" << endl; |
1678 #endif | 1679 #endif |
1679 ((SpectrogramLayer *)this)->sliceableModelReplaced(0, model); | 1680 ((SpectrogramLayer *)this)->sliceableModelReplaced(0, model); |
1680 m_sliceableModel = model; | 1681 m_sliceableModel = model; |
1681 } | 1682 } |
1682 | 1683 |
1728 | 1729 |
1729 m_fftModels.clear(); | 1730 m_fftModels.clear(); |
1730 m_peakCaches.clear(); | 1731 m_peakCaches.clear(); |
1731 | 1732 |
1732 if (m_sliceableModel) { | 1733 if (m_sliceableModel) { |
1733 std::cerr << "SpectrogramLayer: emitting sliceableModelReplaced(" << m_sliceableModel << ", 0)" << std::endl; | 1734 cerr << "SpectrogramLayer: emitting sliceableModelReplaced(" << m_sliceableModel << ", 0)" << endl; |
1734 emit sliceableModelReplaced(m_sliceableModel, 0); | 1735 emit sliceableModelReplaced(m_sliceableModel, 0); |
1735 m_sliceableModel = 0; | 1736 m_sliceableModel = 0; |
1736 } | 1737 } |
1737 } | 1738 } |
1738 | 1739 |
1803 Profiler profiler("SpectrogramLayer::paint", false); | 1804 Profiler profiler("SpectrogramLayer::paint", false); |
1804 | 1805 |
1805 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1806 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1806 SVDEBUG << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << endl; | 1807 SVDEBUG << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << endl; |
1807 | 1808 |
1808 std::cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << std::endl; | 1809 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; |
1809 #endif | 1810 #endif |
1810 | 1811 |
1811 long startFrame = v->getStartFrame(); | 1812 long startFrame = v->getStartFrame(); |
1812 if (startFrame < 0) m_candidateFillStartFrame = 0; | 1813 if (startFrame < 0) m_candidateFillStartFrame = 0; |
1813 else m_candidateFillStartFrame = startFrame; | 1814 else m_candidateFillStartFrame = startFrame; |
1829 | 1830 |
1830 size_t fftSize = getFFTSize(v); | 1831 size_t fftSize = getFFTSize(v); |
1831 /* | 1832 /* |
1832 FFTModel *fft = getFFTModel(v); | 1833 FFTModel *fft = getFFTModel(v); |
1833 if (!fft) { | 1834 if (!fft) { |
1834 std::cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << std::endl; | 1835 cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << endl; |
1835 return; | 1836 return; |
1836 } | 1837 } |
1837 */ | 1838 */ |
1838 ImageCache &cache = m_imageCaches[v]; | 1839 ImageCache &cache = m_imageCaches[v]; |
1839 | 1840 |
1857 | 1858 |
1858 x0 = rect.left(); | 1859 x0 = rect.left(); |
1859 x1 = rect.right() + 1; | 1860 x1 = rect.right() + 1; |
1860 /* | 1861 /* |
1861 float xPixelRatio = float(fft->getResolution()) / float(zoomLevel); | 1862 float xPixelRatio = float(fft->getResolution()) / float(zoomLevel); |
1862 std::cerr << "xPixelRatio = " << xPixelRatio << std::endl; | 1863 cerr << "xPixelRatio = " << xPixelRatio << endl; |
1863 if (xPixelRatio < 1.f) xPixelRatio = 1.f; | 1864 if (xPixelRatio < 1.f) xPixelRatio = 1.f; |
1864 */ | 1865 */ |
1865 if (cache.validArea.width() > 0) { | 1866 if (cache.validArea.width() > 0) { |
1866 | 1867 |
1867 int cw = cache.image.width(); | 1868 int cw = cache.image.width(); |
1875 v->getXForFrame(startFrame) && | 1876 v->getXForFrame(startFrame) && |
1876 cache.validArea.x() <= x0 && | 1877 cache.validArea.x() <= x0 && |
1877 cache.validArea.x() + cache.validArea.width() >= x1) { | 1878 cache.validArea.x() + cache.validArea.width() >= x1) { |
1878 | 1879 |
1879 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1880 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1880 std::cerr << "SpectrogramLayer: image cache good" << std::endl; | 1881 cerr << "SpectrogramLayer: image cache good" << endl; |
1881 #endif | 1882 #endif |
1882 | 1883 |
1883 paint.drawImage(rect, cache.image, rect); | 1884 paint.drawImage(rect, cache.image, rect); |
1884 //!!! | 1885 //!!! |
1885 // paint.drawImage(v->rect(), cache.image, | 1886 // paint.drawImage(v->rect(), cache.image, |
1889 return; | 1890 return; |
1890 | 1891 |
1891 } else { | 1892 } else { |
1892 | 1893 |
1893 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1894 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1894 std::cerr << "SpectrogramLayer: image cache partially OK" << std::endl; | 1895 cerr << "SpectrogramLayer: image cache partially OK" << endl; |
1895 #endif | 1896 #endif |
1896 | 1897 |
1897 recreateWholeImageCache = false; | 1898 recreateWholeImageCache = false; |
1898 | 1899 |
1899 int dx = v->getXForFrame(cache.startFrame) - | 1900 int dx = v->getXForFrame(cache.startFrame) - |
1900 v->getXForFrame(startFrame); | 1901 v->getXForFrame(startFrame); |
1901 | 1902 |
1902 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1903 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1903 std::cerr << "SpectrogramLayer: dx = " << dx << " (image cache " << cw << "x" << ch << ")" << std::endl; | 1904 cerr << "SpectrogramLayer: dx = " << dx << " (image cache " << cw << "x" << ch << ")" << endl; |
1904 #endif | 1905 #endif |
1905 | 1906 |
1906 if (dx != 0 && | 1907 if (dx != 0 && |
1907 dx > -cw && | 1908 dx > -cw && |
1908 dx < cw) { | 1909 dx < cw) { |
1944 cache.validArea = | 1945 cache.validArea = |
1945 QRect(px, cache.validArea.y(), | 1946 QRect(px, cache.validArea.y(), |
1946 pw, cache.validArea.height()); | 1947 pw, cache.validArea.height()); |
1947 | 1948 |
1948 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1949 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1949 std::cerr << "valid area now " | 1950 cerr << "valid area now " |
1950 << px << "," << cache.validArea.y() | 1951 << px << "," << cache.validArea.y() |
1951 << " " << pw << "x" << cache.validArea.height() | 1952 << " " << pw << "x" << cache.validArea.height() |
1952 << std::endl; | 1953 << endl; |
1953 #endif | 1954 #endif |
1954 /* | 1955 /* |
1955 paint.drawImage(rect & cache.validArea, | 1956 paint.drawImage(rect & cache.validArea, |
1956 cache.image, | 1957 cache.image, |
1957 rect & cache.validArea); | 1958 rect & cache.validArea); |
1959 } else if (dx != 0) { | 1960 } else if (dx != 0) { |
1960 | 1961 |
1961 // we scrolled too far to be of use | 1962 // we scrolled too far to be of use |
1962 | 1963 |
1963 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1964 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1964 std::cerr << "dx == " << dx << ": scrolled too far for cache to be useful" << std::endl; | 1965 cerr << "dx == " << dx << ": scrolled too far for cache to be useful" << endl; |
1965 #endif | 1966 #endif |
1966 | 1967 |
1967 cache.validArea = QRect(); | 1968 cache.validArea = QRect(); |
1968 recreateWholeImageCache = true; | 1969 recreateWholeImageCache = true; |
1969 } | 1970 } |
1970 } | 1971 } |
1971 } else { | 1972 } else { |
1972 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1973 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1973 std::cerr << "SpectrogramLayer: image cache useless" << std::endl; | 1974 cerr << "SpectrogramLayer: image cache useless" << endl; |
1974 if (int(cache.zoomLevel) != zoomLevel) { | 1975 if (int(cache.zoomLevel) != zoomLevel) { |
1975 std::cerr << "(cache zoomLevel " << cache.zoomLevel | 1976 cerr << "(cache zoomLevel " << cache.zoomLevel |
1976 << " != " << zoomLevel << ")" << std::endl; | 1977 << " != " << zoomLevel << ")" << endl; |
1977 } | 1978 } |
1978 if (cw != v->width()) { | 1979 if (cw != v->width()) { |
1979 std::cerr << "(cache width " << cw | 1980 cerr << "(cache width " << cw |
1980 << " != " << v->width(); | 1981 << " != " << v->width(); |
1981 } | 1982 } |
1982 if (ch != v->height()) { | 1983 if (ch != v->height()) { |
1983 std::cerr << "(cache height " << ch | 1984 cerr << "(cache height " << ch |
1984 << " != " << v->height(); | 1985 << " != " << v->height(); |
1985 } | 1986 } |
1986 #endif | 1987 #endif |
1987 cache.validArea = QRect(); | 1988 cache.validArea = QRect(); |
1988 // recreateWholeImageCache = true; | 1989 // recreateWholeImageCache = true; |
1989 } | 1990 } |
1990 } | 1991 } |
1991 | 1992 |
1992 if (updateViewMagnitudes(v)) { | 1993 if (updateViewMagnitudes(v)) { |
1993 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1994 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1994 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 1995 cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << endl; |
1995 #endif | 1996 #endif |
1996 if (m_normalizeVisibleArea) { | 1997 if (m_normalizeVisibleArea) { |
1997 cache.validArea = QRect(); | 1998 cache.validArea = QRect(); |
1998 recreateWholeImageCache = true; | 1999 recreateWholeImageCache = true; |
1999 } | 2000 } |
2000 } else { | 2001 } else { |
2001 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2002 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2002 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 2003 cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << endl; |
2003 #endif | 2004 #endif |
2004 } | 2005 } |
2005 | 2006 |
2006 if (recreateWholeImageCache) { | 2007 if (recreateWholeImageCache) { |
2007 x0 = 0; | 2008 x0 = 0; |
2038 | 2039 |
2039 if (paintBlockWidth < 20) paintBlockWidth = 20; | 2040 if (paintBlockWidth < 20) paintBlockWidth = 20; |
2040 } | 2041 } |
2041 | 2042 |
2042 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2043 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2043 std::cerr << "[" << this << "]: last paint width: " << m_lastPaintBlockWidth << ", last paint time: " << m_lastPaintTime << ", new paint width: " << paintBlockWidth << std::endl; | 2044 cerr << "[" << this << "]: last paint width: " << m_lastPaintBlockWidth << ", last paint time: " << m_lastPaintTime << ", new paint width: " << paintBlockWidth << endl; |
2044 #endif | 2045 #endif |
2045 | 2046 |
2046 // We always paint the full height when refreshing the cache. | 2047 // We always paint the full height when refreshing the cache. |
2047 // Smaller heights can be used when painting direct from cache | 2048 // Smaller heights can be used when painting direct from cache |
2048 // (further up in this function), but we want to ensure the cache | 2049 // (further up in this function), but we want to ensure the cache |
2063 int vx0 = 0, vx1 = 0; | 2064 int vx0 = 0, vx1 = 0; |
2064 vx0 = cache.validArea.x(); | 2065 vx0 = cache.validArea.x(); |
2065 vx1 = cache.validArea.x() + cache.validArea.width(); | 2066 vx1 = cache.validArea.x() + cache.validArea.width(); |
2066 | 2067 |
2067 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2068 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2068 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl; | 2069 cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << endl; |
2069 #endif | 2070 #endif |
2070 if (x0 < vx0) { | 2071 if (x0 < vx0) { |
2071 if (x0 + paintBlockWidth < vx0) { | 2072 if (x0 + paintBlockWidth < vx0) { |
2072 x0 = vx0 - paintBlockWidth; | 2073 x0 = vx0 - paintBlockWidth; |
2073 } | 2074 } |
2094 std::max(vx1 - std::min(vx0, x0), | 2095 std::max(vx1 - std::min(vx0, x0), |
2095 x1 - std::min(vx0, x0)), | 2096 x1 - std::min(vx0, x0)), |
2096 cache.validArea.height()); | 2097 cache.validArea.height()); |
2097 | 2098 |
2098 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2099 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2099 std::cerr << "Valid area becomes " << cache.validArea.x() | 2100 cerr << "Valid area becomes " << cache.validArea.x() |
2100 << ", " << cache.validArea.y() << ", " | 2101 << ", " << cache.validArea.y() << ", " |
2101 << cache.validArea.width() << "x" | 2102 << cache.validArea.width() << "x" |
2102 << cache.validArea.height() << std::endl; | 2103 << cache.validArea.height() << endl; |
2103 #endif | 2104 #endif |
2104 | 2105 |
2105 } else { | 2106 } else { |
2106 if (x1 > x0 + paintBlockWidth) { | 2107 if (x1 > x0 + paintBlockWidth) { |
2107 int sfx = x1; | 2108 int sfx = x1; |
2114 x0 = mid - paintBlockWidth/2; | 2115 x0 = mid - paintBlockWidth/2; |
2115 x1 = x0 + paintBlockWidth; | 2116 x1 = x0 + paintBlockWidth; |
2116 } | 2117 } |
2117 } | 2118 } |
2118 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2119 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2119 std::cerr << "Valid area becomes " << x0 << ", 0, " << (x1-x0) | 2120 cerr << "Valid area becomes " << x0 << ", 0, " << (x1-x0) |
2120 << "x" << h << std::endl; | 2121 << "x" << h << endl; |
2121 #endif | 2122 #endif |
2122 cache.validArea = QRect(x0, 0, x1 - x0, h); | 2123 cache.validArea = QRect(x0, 0, x1 - x0, h); |
2123 } | 2124 } |
2124 | 2125 |
2125 /* | 2126 /* |
2129 } | 2130 } |
2130 */ | 2131 */ |
2131 int w = x1 - x0; | 2132 int w = x1 - x0; |
2132 | 2133 |
2133 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2134 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2134 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl; | 2135 cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << endl; |
2135 #endif | 2136 #endif |
2136 | 2137 |
2137 int sr = m_model->getSampleRate(); | 2138 int sr = m_model->getSampleRate(); |
2138 | 2139 |
2139 // Set minFreq and maxFreq to the frequency extents of the possibly | 2140 // Set minFreq and maxFreq to the frequency extents of the possibly |
2154 } | 2155 } |
2155 | 2156 |
2156 size_t minbin = 1; | 2157 size_t minbin = 1; |
2157 if (m_minFrequency > 0) { | 2158 if (m_minFrequency > 0) { |
2158 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.001); | 2159 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.001); |
2159 // std::cerr << "m_minFrequency = " << m_minFrequency << " -> minbin = " << minbin << std::endl; | 2160 // cerr << "m_minFrequency = " << m_minFrequency << " -> minbin = " << minbin << endl; |
2160 if (minbin < 1) minbin = 1; | 2161 if (minbin < 1) minbin = 1; |
2161 if (minbin >= maxbin) minbin = maxbin - 1; | 2162 if (minbin >= maxbin) minbin = maxbin - 1; |
2162 } | 2163 } |
2163 | 2164 |
2164 int zpl = getZeroPadLevel(v) + 1; | 2165 int zpl = getZeroPadLevel(v) + 1; |
2174 if (fftSize != m_fftSize) { | 2175 if (fftSize != m_fftSize) { |
2175 displayMinFreq = getEffectiveMinFrequency(); | 2176 displayMinFreq = getEffectiveMinFrequency(); |
2176 displayMaxFreq = getEffectiveMaxFrequency(); | 2177 displayMaxFreq = getEffectiveMaxFrequency(); |
2177 } | 2178 } |
2178 | 2179 |
2179 // std::cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << std::endl; | 2180 // cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << endl; |
2180 | 2181 |
2181 int increment = getWindowIncrement(); | 2182 int increment = getWindowIncrement(); |
2182 | 2183 |
2183 bool logarithmic = (m_frequencyScale == LogFrequencyScale); | 2184 bool logarithmic = (m_frequencyScale == LogFrequencyScale); |
2184 /* | 2185 /* |
2195 bool overallMagChanged = false; | 2196 bool overallMagChanged = false; |
2196 | 2197 |
2197 bool fftSuspended = false; | 2198 bool fftSuspended = false; |
2198 | 2199 |
2199 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2200 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2200 std::cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << std::endl; | 2201 cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; |
2201 #endif | 2202 #endif |
2202 | 2203 |
2203 bool runOutOfData = false; | 2204 bool runOutOfData = false; |
2204 | 2205 |
2205 if (w == 0) { | 2206 if (w == 0) { |
2335 xPixelRatio, | 2336 xPixelRatio, |
2336 h, yforbin); | 2337 h, yforbin); |
2337 | 2338 |
2338 if (runOutOfData) { | 2339 if (runOutOfData) { |
2339 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2340 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2340 std::cerr << "Run out of data -- dropping out of loop" << std::endl; | 2341 cerr << "Run out of data -- dropping out of loop" << endl; |
2341 #endif | 2342 #endif |
2342 break; | 2343 break; |
2343 } | 2344 } |
2344 } | 2345 } |
2345 */ | 2346 */ |
2346 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2347 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2347 // std::cerr << pixels << " pixels drawn" << std::endl; | 2348 // cerr << pixels << " pixels drawn" << endl; |
2348 #endif | 2349 #endif |
2349 | 2350 |
2350 if (overallMagChanged) { | 2351 if (overallMagChanged) { |
2351 m_viewMags[v] = overallMag; | 2352 m_viewMags[v] = overallMag; |
2352 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2353 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2353 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl; | 2354 cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << endl; |
2354 #endif | 2355 #endif |
2355 } else { | 2356 } else { |
2356 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2357 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2357 std::cerr << "Overall mag unchanged at [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 2358 cerr << "Overall mag unchanged at [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << endl; |
2358 #endif | 2359 #endif |
2359 } | 2360 } |
2360 | 2361 |
2361 outerprof.end(); | 2362 outerprof.end(); |
2362 | 2363 |
2462 cache.validArea.width()), | 2463 cache.validArea.width()), |
2463 h); | 2464 h); |
2464 } | 2465 } |
2465 } else { | 2466 } else { |
2466 // overallMagChanged | 2467 // overallMagChanged |
2467 std::cerr << "\noverallMagChanged - updating all\n" << std::endl; | 2468 cerr << "\noverallMagChanged - updating all\n" << endl; |
2468 cache.validArea = QRect(); | 2469 cache.validArea = QRect(); |
2469 v->update(); | 2470 v->update(); |
2470 } | 2471 } |
2471 } | 2472 } |
2472 | 2473 |
2538 if (sx < 0 || sx >= int(fft->getWidth())) continue; | 2539 if (sx < 0 || sx >= int(fft->getWidth())) continue; |
2539 | 2540 |
2540 if (!m_synchronous) { | 2541 if (!m_synchronous) { |
2541 if (!fft->isColumnAvailable(sx)) { | 2542 if (!fft->isColumnAvailable(sx)) { |
2542 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2543 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2543 std::cerr << "Met unavailable column at col " << sx << std::endl; | 2544 cerr << "Met unavailable column at col " << sx << endl; |
2544 #endif | 2545 #endif |
2545 return false; | 2546 return false; |
2546 } | 2547 } |
2547 } | 2548 } |
2548 | 2549 |
2590 } | 2591 } |
2591 | 2592 |
2592 if (mag.isSet()) { | 2593 if (mag.isSet()) { |
2593 if (sx >= int(m_columnMags.size())) { | 2594 if (sx >= int(m_columnMags.size())) { |
2594 #ifdef DEBUG_SPECTROGRAM | 2595 #ifdef DEBUG_SPECTROGRAM |
2595 std::cerr << "INTERNAL ERROR: " << sx << " >= " | 2596 cerr << "INTERNAL ERROR: " << sx << " >= " |
2596 << m_columnMags.size() | 2597 << m_columnMags.size() |
2597 << " at SpectrogramLayer.cpp::paintDrawBuffer" | 2598 << " at SpectrogramLayer.cpp::paintDrawBuffer" |
2598 << std::endl; | 2599 << endl; |
2599 #endif | 2600 #endif |
2600 } else { | 2601 } else { |
2601 m_columnMags[sx].sample(mag); | 2602 m_columnMags[sx].sample(mag); |
2602 if (overallMag.sample(mag)) overallMagChanged = true; | 2603 if (overallMag.sample(mag)) overallMagChanged = true; |
2603 } | 2604 } |
2687 for (int y = 0; y < h; ++y) peaks[y] = 0.f; | 2688 for (int y = 0; y < h; ++y) peaks[y] = 0.f; |
2688 | 2689 |
2689 for (int sx = sx0; sx < sx1; ++sx) { | 2690 for (int sx = sx0; sx < sx1; ++sx) { |
2690 | 2691 |
2691 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2692 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2692 // std::cerr << "sx = " << sx << std::endl; | 2693 // cerr << "sx = " << sx << endl; |
2693 #endif | 2694 #endif |
2694 | 2695 |
2695 if (sx < 0 || sx >= int(sourceModel->getWidth())) continue; | 2696 if (sx < 0 || sx >= int(sourceModel->getWidth())) continue; |
2696 | 2697 |
2697 if (!m_synchronous) { | 2698 if (!m_synchronous) { |
2698 if (!sourceModel->isColumnAvailable(sx)) { | 2699 if (!sourceModel->isColumnAvailable(sx)) { |
2699 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2700 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2700 std::cerr << "Met unavailable column at col " << sx << std::endl; | 2701 cerr << "Met unavailable column at col " << sx << endl; |
2701 #endif | 2702 #endif |
2702 return false; | 2703 return false; |
2703 } | 2704 } |
2704 } | 2705 } |
2705 | 2706 |
2803 } | 2804 } |
2804 | 2805 |
2805 if (mag.isSet()) { | 2806 if (mag.isSet()) { |
2806 if (sx >= int(m_columnMags.size())) { | 2807 if (sx >= int(m_columnMags.size())) { |
2807 #ifdef DEBUG_SPECTROGRAM | 2808 #ifdef DEBUG_SPECTROGRAM |
2808 std::cerr << "INTERNAL ERROR: " << sx << " >= " | 2809 cerr << "INTERNAL ERROR: " << sx << " >= " |
2809 << m_columnMags.size() | 2810 << m_columnMags.size() |
2810 << " at SpectrogramLayer.cpp::paintDrawBuffer" | 2811 << " at SpectrogramLayer.cpp::paintDrawBuffer" |
2811 << std::endl; | 2812 << endl; |
2812 #endif | 2813 #endif |
2813 } else { | 2814 } else { |
2814 m_columnMags[sx].sample(mag); | 2815 m_columnMags[sx].sample(mag); |
2815 if (overallMag.sample(mag)) overallMagChanged = true; | 2816 if (overallMag.sample(mag)) overallMagChanged = true; |
2816 } | 2817 } |
2844 QPoint localPos; | 2845 QPoint localPos; |
2845 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { | 2846 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { |
2846 return; | 2847 return; |
2847 } | 2848 } |
2848 | 2849 |
2849 // std::cerr << "SpectrogramLayer: illuminateLocalFeatures(" | 2850 // cerr << "SpectrogramLayer: illuminateLocalFeatures(" |
2850 // << localPos.x() << "," << localPos.y() << ")" << std::endl; | 2851 // << localPos.x() << "," << localPos.y() << ")" << endl; |
2851 | 2852 |
2852 float s0, s1; | 2853 float s0, s1; |
2853 float f0, f1; | 2854 float f0, f1; |
2854 | 2855 |
2855 if (getXBinRange(v, localPos.x(), s0, s1) && | 2856 if (getXBinRange(v, localPos.x(), s0, s1) && |
2862 int x1 = v->getXForFrame((s1i + 1) * getWindowIncrement()); | 2863 int x1 = v->getXForFrame((s1i + 1) * getWindowIncrement()); |
2863 | 2864 |
2864 int y1 = int(getYForFrequency(v, f1)); | 2865 int y1 = int(getYForFrequency(v, f1)); |
2865 int y0 = int(getYForFrequency(v, f0)); | 2866 int y0 = int(getYForFrequency(v, f0)); |
2866 | 2867 |
2867 // std::cerr << "SpectrogramLayer: illuminate " | 2868 // cerr << "SpectrogramLayer: illuminate " |
2868 // << x0 << "," << y1 << " -> " << x1 << "," << y0 << std::endl; | 2869 // << x0 << "," << y1 << " -> " << x1 << "," << y0 << endl; |
2869 | 2870 |
2870 paint.setPen(v->getForeground()); | 2871 paint.setPen(v->getForeground()); |
2871 | 2872 |
2872 //!!! should we be using paintCrosshairs for this? | 2873 //!!! should we be using paintCrosshairs for this? |
2873 | 2874 |
3004 void | 3005 void |
3005 SpectrogramLayer::measureDoubleClick(View *v, QMouseEvent *e) | 3006 SpectrogramLayer::measureDoubleClick(View *v, QMouseEvent *e) |
3006 { | 3007 { |
3007 ImageCache &cache = m_imageCaches[v]; | 3008 ImageCache &cache = m_imageCaches[v]; |
3008 | 3009 |
3009 std::cerr << "cache width: " << cache.image.width() << ", height: " | 3010 cerr << "cache width: " << cache.image.width() << ", height: " |
3010 << cache.image.height() << std::endl; | 3011 << cache.image.height() << endl; |
3011 | 3012 |
3012 QImage image = cache.image; | 3013 QImage image = cache.image; |
3013 | 3014 |
3014 ImageRegionFinder finder; | 3015 ImageRegionFinder finder; |
3015 QRect rect = finder.findRegionExtents(&image, e->pos()); | 3016 QRect rect = finder.findRegionExtents(&image, e->pos()); |
3433 | 3434 |
3434 if (m_frequencyScale == LogFrequencyScale) { | 3435 if (m_frequencyScale == LogFrequencyScale) { |
3435 | 3436 |
3436 // piano keyboard | 3437 // piano keyboard |
3437 | 3438 |
3438 paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h); | 3439 PianoScale().paintPianoVertical |
3439 | 3440 (v, paint, QRect(w - pkw - 1, 0, pkw, h), |
3440 float minf = getEffectiveMinFrequency(); | 3441 getEffectiveMinFrequency(), getEffectiveMaxFrequency()); |
3441 float maxf = getEffectiveMaxFrequency(); | |
3442 | |
3443 int py = h, ppy = h; | |
3444 paint.setBrush(paint.pen().color()); | |
3445 | |
3446 for (int i = 0; i < 128; ++i) { | |
3447 | |
3448 float f = Pitch::getFrequencyForPitch(i); | |
3449 int y = lrintf(v->getYForFrequency(f, minf, maxf, true)); | |
3450 | |
3451 if (y < -2) break; | |
3452 if (y > h + 2) { | |
3453 continue; | |
3454 } | |
3455 | |
3456 int n = (i % 12); | |
3457 | |
3458 if (n == 1) { | |
3459 // C# -- fill the C from here | |
3460 QColor col = Qt::gray; | |
3461 if (i == 61) { // filling middle C | |
3462 col = Qt::blue; | |
3463 col = col.light(150); | |
3464 } | |
3465 if (ppy - y > 2) { | |
3466 paint.fillRect(w - pkw, | |
3467 y, | |
3468 pkw, | |
3469 (py + ppy) / 2 - y, | |
3470 col); | |
3471 } | |
3472 } | |
3473 | |
3474 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { | |
3475 // black notes | |
3476 paint.drawLine(w - pkw, y, w, y); | |
3477 int rh = ((py - y) / 4) * 2; | |
3478 if (rh < 2) rh = 2; | |
3479 paint.drawRect(w - pkw, y - (py-y)/4, pkw/2, rh); | |
3480 } else if (n == 0 || n == 5) { | |
3481 // C, F | |
3482 if (py < h) { | |
3483 paint.drawLine(w - pkw, (y + py) / 2, w, (y + py) / 2); | |
3484 } | |
3485 } | |
3486 | |
3487 ppy = py; | |
3488 py = y; | |
3489 } | |
3490 } | 3442 } |
3491 | 3443 |
3492 m_haveDetailedScale = detailed; | 3444 m_haveDetailedScale = detailed; |
3493 } | 3445 } |
3494 | 3446 |
3582 if (!m_model) return; | 3534 if (!m_model) return; |
3583 | 3535 |
3584 float dmin = m_minFrequency, dmax = m_maxFrequency; | 3536 float dmin = m_minFrequency, dmax = m_maxFrequency; |
3585 // getDisplayExtents(dmin, dmax); | 3537 // getDisplayExtents(dmin, dmax); |
3586 | 3538 |
3587 // std::cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << std::endl; | 3539 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl; |
3588 | 3540 |
3589 int sr = m_model->getSampleRate(); | 3541 int sr = m_model->getSampleRate(); |
3590 SpectrogramRangeMapper mapper(sr, m_fftSize); | 3542 SpectrogramRangeMapper mapper(sr, m_fftSize); |
3591 float newdist = mapper.getValueForPosition(step); | 3543 float newdist = mapper.getValueForPosition(step); |
3592 | 3544 |
3616 // so newmax = (newdist + sqrtf(newdist^2 + 4dmin.dmax)) / 2 | 3568 // so newmax = (newdist + sqrtf(newdist^2 + 4dmin.dmax)) / 2 |
3617 | 3569 |
3618 newmax = (newdist + sqrtf(newdist*newdist + 4*dmin*dmax)) / 2; | 3570 newmax = (newdist + sqrtf(newdist*newdist + 4*dmin*dmax)) / 2; |
3619 newmin = newmax - newdist; | 3571 newmin = newmax - newdist; |
3620 | 3572 |
3621 // std::cerr << "newmin = " << newmin << ", newmax = " << newmax << std::endl; | 3573 // cerr << "newmin = " << newmin << ", newmax = " << newmax << endl; |
3622 | 3574 |
3623 } else { | 3575 } else { |
3624 float dmid = (dmax + dmin) / 2; | 3576 float dmid = (dmax + dmin) / 2; |
3625 newmin = dmid - newdist / 2; | 3577 newmin = dmid - newdist / 2; |
3626 newmax = dmid + newdist / 2; | 3578 newmax = dmid + newdist / 2; |