comparison layer/SpectrogramLayer.cpp @ 331:d2d2521a6c7e

* Some fixes to cache repainting strategy -- should make things a little quicker, but some glitches remain
author Chris Cannam
date Mon, 19 Nov 2007 15:50:14 +0000
parents 29fcf125f98b
children 0a74248af622
comparison
equal deleted inserted replaced
328:b6df8b44b98d 331:d2d2521a6c7e
899 void 899 void
900 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) 900 SpectrogramLayer::setLayerDormant(const View *v, bool dormant)
901 { 901 {
902 if (dormant) { 902 if (dormant) {
903 903
904 #ifdef DEBUG_SPECTROGRAM_REPAINT
905 std::cerr << "SpectrogramLayer::setLayerDormant(" << dormant << ")"
906 << std::endl;
907 #endif
908
904 if (isLayerDormant(v)) { 909 if (isLayerDormant(v)) {
905 return; 910 return;
906 } 911 }
907 912
908 Layer::setLayerDormant(v, true); 913 Layer::setLayerDormant(v, true);
1752 1757
1753 if (dx != 0 && 1758 if (dx != 0 &&
1754 dx > -cache.pixmap.width() && 1759 dx > -cache.pixmap.width() &&
1755 dx < cache.pixmap.width()) { 1760 dx < cache.pixmap.width()) {
1756 1761
1757 #if defined(Q_WS_WIN32) || defined(Q_WS_MAC) 1762 QPixmap tmp = cache.pixmap;
1758 // Copying a pixmap to itself doesn't work 1763 QPainter cachePainter(&cache.pixmap);
1759 // properly on Windows or Mac (it only works when 1764 if (dx < 0) {
1760 // moving in one direction). 1765 cachePainter.drawPixmap
1761 1766 (QRect(0, 0,
1762 //!!! Need a utility function for this 1767 cache.pixmap.width() + dx,
1763 1768 cache.pixmap.height()),
1764 static QPixmap *tmpPixmap = 0; 1769 tmp,
1765 if (!tmpPixmap || 1770 QRect(-dx, 0,
1766 tmpPixmap->width() != cache.pixmap.width() || 1771 cache.pixmap.width() + dx,
1767 tmpPixmap->height() != cache.pixmap.height()) { 1772 cache.pixmap.height()));
1768 delete tmpPixmap; 1773 } else {
1769 tmpPixmap = new QPixmap(cache.pixmap.width(), 1774 cachePainter.drawPixmap
1770 cache.pixmap.height()); 1775 (QRect(dx, 0,
1771 } 1776 cache.pixmap.width() - dx,
1772 QPainter cachePainter; 1777 cache.pixmap.height()),
1773 cachePainter.begin(tmpPixmap); 1778 tmp,
1774 cachePainter.drawPixmap(0, 0, cache.pixmap); 1779 QRect(0, 0,
1775 cachePainter.end(); 1780 cache.pixmap.width() - dx,
1776 cachePainter.begin(&cache.pixmap); 1781 cache.pixmap.height()));
1777 cachePainter.drawPixmap(dx, 0, *tmpPixmap); 1782 }
1778 cachePainter.end();
1779 #else
1780 QPainter cachePainter(&cache.pixmap);
1781 cachePainter.drawPixmap(dx, 0, cache.pixmap);
1782 cachePainter.end();
1783 #endif
1784 1783
1785 int px = cache.validArea.x(); 1784 int px = cache.validArea.x();
1786 int pw = cache.validArea.width(); 1785 int pw = cache.validArea.width();
1787 1786
1788 if (dx < 0) { 1787 if (dx < 0) {
1806 1805
1807 cache.validArea = 1806 cache.validArea =
1808 QRect(px, cache.validArea.y(), 1807 QRect(px, cache.validArea.y(),
1809 pw, cache.validArea.height()); 1808 pw, cache.validArea.height());
1810 1809
1810 #ifdef DEBUG_SPECTROGRAM_REPAINT
1811 std::cerr << "valid area now "
1812 << px << "," << cache.validArea.y()
1813 << " " << pw << "x" << cache.validArea.height()
1814 << std::endl;
1815 #endif
1816
1811 paint.drawPixmap(rect & cache.validArea, 1817 paint.drawPixmap(rect & cache.validArea,
1812 cache.pixmap, 1818 cache.pixmap,
1813 rect & cache.validArea); 1819 rect & cache.validArea);
1814 } 1820
1821 } else if (dx != 0) {
1822
1823 // we scrolled too far to be of use
1824
1825 cache.validArea = QRect();
1826 recreateWholePixmapCache = true;
1827 }
1815 } 1828 }
1816 } else { 1829 } else {
1817 #ifdef DEBUG_SPECTROGRAM_REPAINT 1830 #ifdef DEBUG_SPECTROGRAM_REPAINT
1818 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl; 1831 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl;
1819 if (int(cache.zoomLevel) != zoomLevel) { 1832 if (int(cache.zoomLevel) != zoomLevel) {
1835 1848
1836 if (updateViewMagnitudes(v)) { 1849 if (updateViewMagnitudes(v)) {
1837 #ifdef DEBUG_SPECTROGRAM_REPAINT 1850 #ifdef DEBUG_SPECTROGRAM_REPAINT
1838 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; 1851 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
1839 #endif 1852 #endif
1840 recreateWholePixmapCache = true; 1853 if (m_normalizeVisibleArea) {
1854 cache.validArea = QRect();
1855 recreateWholePixmapCache = true;
1856 }
1841 } else { 1857 } else {
1842 #ifdef DEBUG_SPECTROGRAM_REPAINT 1858 #ifdef DEBUG_SPECTROGRAM_REPAINT
1843 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; 1859 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
1844 #endif 1860 #endif
1845 } 1861 }
1885 1901
1886 int h = v->height(); 1902 int h = v->height();
1887 1903
1888 if (cache.validArea.width() > 0) { 1904 if (cache.validArea.width() > 0) {
1889 1905
1906 // If part of the cache is known to be valid, select a strip
1907 // immediately to left or right of the valid part
1908
1890 int vx0 = 0, vx1 = 0; 1909 int vx0 = 0, vx1 = 0;
1891 vx0 = cache.validArea.x(); 1910 vx0 = cache.validArea.x();
1892 vx1 = cache.validArea.x() + cache.validArea.width(); 1911 vx1 = cache.validArea.x() + cache.validArea.width();
1893 1912
1894 #ifdef DEBUG_SPECTROGRAM_REPAINT 1913 #ifdef DEBUG_SPECTROGRAM_REPAINT
1895 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl; 1914 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << ", paintBlockWidth " << paintBlockWidth << std::endl;
1896 #endif 1915 #endif
1897 if (x0 < vx0) { 1916 if (x0 < vx0) {
1898 if (x0 + paintBlockWidth < vx0) { 1917 if (x0 + paintBlockWidth < vx0) {
1899 x0 = vx0 - paintBlockWidth; 1918 x0 = vx0 - paintBlockWidth;
1919 }
1920 x1 = vx0;
1921 } else if (x0 >= vx1) {
1922 x0 = vx1;
1923 if (x1 > x0 + paintBlockWidth) {
1924 x1 = x0 + paintBlockWidth;
1925 }
1926 } else {
1927 // x0 is within the valid area
1928 if (x1 > vx1) {
1929 x0 = vx1;
1930 if (x0 + paintBlockWidth < x1) {
1931 x1 = x0 + paintBlockWidth;
1932 }
1900 } else { 1933 } else {
1901 x0 = 0; 1934 x1 = x0; // it's all valid, paint nothing
1902 }
1903 } else if (x0 > vx1) {
1904 x0 = vx1;
1905 }
1906
1907 if (x1 < vx0) {
1908 x1 = vx0;
1909 } else if (x1 > vx1) {
1910 if (vx1 + paintBlockWidth < x1) {
1911 x1 = vx1 + paintBlockWidth;
1912 } else {
1913 x1 = v->width();
1914 } 1935 }
1915 } 1936 }
1916 1937
1917 cache.validArea = QRect 1938 cache.validArea = QRect
1918 (std::min(vx0, x0), cache.validArea.y(), 1939 (std::min(vx0, x0), cache.validArea.y(),
1919 std::max(vx1 - std::min(vx0, x0), 1940 std::max(vx1 - std::min(vx0, x0),
1920 x1 - std::min(vx0, x0)), 1941 x1 - std::min(vx0, x0)),
1921 cache.validArea.height()); 1942 cache.validArea.height());
2027 std::cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << std::endl; 2048 std::cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << std::endl;
2028 #endif 2049 #endif
2029 2050
2030 bool runOutOfData = false; 2051 bool runOutOfData = false;
2031 2052
2053 if (w == 0) {
2054 std::cerr << "*** NOTE: w == 0" << std::endl;
2055 }
2056
2057 #ifdef DEBUG_SPECTROGRAM_REPAINT
2058 size_t pixels = 0;
2059 #endif
2060
2032 for (int x = 0; x < w; ++x) { 2061 for (int x = 0; x < w; ++x) {
2033 2062
2034 if (runOutOfData) break; 2063 if (runOutOfData) {
2064 #ifdef DEBUG_SPECTROGRAM_REPAINT
2065 std::cerr << "Run out of data -- dropping out of loop" << std::endl;
2066 #endif
2067 break;
2068 }
2035 2069
2036 for (int y = 0; y < h; ++y) { 2070 for (int y = 0; y < h; ++y) {
2037 ymag[y] = 0.f; 2071 ymag[y] = 0.f;
2038 ydiv[y] = 0.f; 2072 ydiv[y] = 0.f;
2039 } 2073 }
2048 int s0i = int(s0 + 0.001); 2082 int s0i = int(s0 + 0.001);
2049 int s1i = int(s1); 2083 int s1i = int(s1);
2050 2084
2051 if (s1i >= int(fft->getWidth())) { 2085 if (s1i >= int(fft->getWidth())) {
2052 if (s0i >= int(fft->getWidth())) { 2086 if (s0i >= int(fft->getWidth())) {
2087 #ifdef DEBUG_SPECTROGRAM_REPAINT
2088 std::cerr << "Column " << s0i << " out of range" << std::endl;
2089 #endif
2053 continue; 2090 continue;
2054 } else { 2091 } else {
2055 s1i = s0i; 2092 s1i = s0i;
2056 } 2093 }
2057 } 2094 }
2216 2253
2217 assert(x <= m_drawBuffer.width()); 2254 assert(x <= m_drawBuffer.width());
2218 QColor c = m_palette.getColour(pixel); 2255 QColor c = m_palette.getColour(pixel);
2219 m_drawBuffer.setPixel(x, y, 2256 m_drawBuffer.setPixel(x, y,
2220 qRgb(c.red(), c.green(), c.blue())); 2257 qRgb(c.red(), c.green(), c.blue()));
2258 #ifdef DEBUG_SPECTROGRAM_REPAINT
2259 ++pixels;
2260 #endif
2221 } 2261 }
2222 } 2262 }
2223 } 2263 }
2224 2264
2265 #ifdef DEBUG_SPECTROGRAM_REPAINT
2266 std::cerr << pixels << " pixels drawn" << std::endl;
2267 #endif
2268
2225 if (overallMagChanged) { 2269 if (overallMagChanged) {
2226 m_viewMags[v] = overallMag; 2270 m_viewMags[v] = overallMag;
2227 #ifdef DEBUG_SPECTROGRAM_REPAINT 2271 #ifdef DEBUG_SPECTROGRAM_REPAINT
2228 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl; 2272 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl;
2229 #endif 2273 #endif
2233 #endif 2277 #endif
2234 } 2278 }
2235 2279
2236 Profiler profiler2("SpectrogramLayer::paint: draw image", true); 2280 Profiler profiler2("SpectrogramLayer::paint: draw image", true);
2237 2281
2238 #ifdef DEBUG_SPECTROGRAM_REPAINT 2282 if (w > 0) {
2239 std::cerr << "Painting " << w << "x" << rect.height() 2283 #ifdef DEBUG_SPECTROGRAM_REPAINT
2240 << " from draw buffer at " << 0 << "," << rect.y() 2284 std::cerr << "Painting " << w << "x" << rect.height()
2241 << " to window at " << x0 << "," << rect.y() << std::endl; 2285 << " from draw buffer at " << 0 << "," << rect.y()
2242 #endif 2286 << " to window at " << x0 << "," << rect.y() << std::endl;
2243 2287 #endif
2244 paint.drawImage(x0, rect.y(), m_drawBuffer, 0, rect.y(), w, rect.height()); 2288
2289 paint.drawImage(x0, rect.y(), m_drawBuffer,
2290 0, rect.y(), w, rect.height());
2291 }
2245 2292
2246 if (recreateWholePixmapCache) { 2293 if (recreateWholePixmapCache) {
2294 std::cerr << "Recreating pixmap cache: width = " << v->width()
2295 << ", height = " << h << std::endl;
2247 cache.pixmap = QPixmap(v->width(), h); 2296 cache.pixmap = QPixmap(v->width(), h);
2248 } 2297 }
2249 2298
2250 #ifdef DEBUG_SPECTROGRAM_REPAINT 2299 if (w > 0) {
2251 std::cerr << "Painting " << w << "x" << h 2300 #ifdef DEBUG_SPECTROGRAM_REPAINT
2252 << " from draw buffer at " << 0 << "," << 0 2301 std::cerr << "Painting " << w << "x" << h
2253 << " to cache at " << x0 << "," << 0 << std::endl; 2302 << " from draw buffer at " << 0 << "," << 0
2254 #endif 2303 << " to cache at " << x0 << "," << 0 << std::endl;
2255 2304 #endif
2256 QPainter cachePainter(&cache.pixmap); 2305
2257 cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h); 2306 QPainter cachePainter(&cache.pixmap);
2258 cachePainter.end(); 2307 cachePainter.drawImage(x0, 0, m_drawBuffer, 0, 0, w, h);
2308 cachePainter.end();
2309 }
2310
2311 cache.startFrame = startFrame;
2312 cache.zoomLevel = zoomLevel;
2259 2313
2260 if (!m_normalizeVisibleArea || !overallMagChanged) { 2314 if (!m_normalizeVisibleArea || !overallMagChanged) {
2261 2315
2262 cache.startFrame = startFrame;
2263 cache.zoomLevel = zoomLevel;
2264
2265 if (cache.validArea.x() > 0) { 2316 if (cache.validArea.x() > 0) {
2266 #ifdef DEBUG_SPECTROGRAM_REPAINT 2317 #ifdef DEBUG_SPECTROGRAM_REPAINT
2267 std::cerr << "SpectrogramLayer::paint() updating left (0, " 2318 std::cerr << "SpectrogramLayer::paint() updating left (0, "
2268 << cache.validArea.x() << ")" << std::endl; 2319 << cache.validArea.x() << ")" << std::endl;
2269 #endif 2320 #endif
2286 cache.validArea.width()), 2337 cache.validArea.width()),
2287 h); 2338 h);
2288 } 2339 }
2289 } else { 2340 } else {
2290 // overallMagChanged 2341 // overallMagChanged
2342 std::cerr << "\noverallMagChanged - updating all\n" << std::endl;
2291 cache.validArea = QRect(); 2343 cache.validArea = QRect();
2292 v->update(); 2344 v->update();
2293 } 2345 }
2294 2346
2295 illuminateLocalFeatures(v, paint); 2347 illuminateLocalFeatures(v, paint);