Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 1026:53110ace211f spectrogram-minor-refactor
Draw right-to-left when adjoining an existing cache valid area on the right
author | Chris Cannam |
---|---|
date | Tue, 26 Jan 2016 13:19:53 +0000 |
parents | c02de0e34233 |
children | dade9bfc7695 |
comparison
equal
deleted
inserted
replaced
1025:c02de0e34233 | 1026:53110ace211f |
---|---|
1674 // It's practically FORTRAN 77 in its clarity and linearity. | 1674 // It's practically FORTRAN 77 in its clarity and linearity. |
1675 | 1675 |
1676 Profiler profiler("SpectrogramLayer::paint", false); | 1676 Profiler profiler("SpectrogramLayer::paint", false); |
1677 | 1677 |
1678 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1678 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1679 cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl; | 1679 cerr << "SpectrogramLayer::paint() entering: m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl; |
1680 | 1680 |
1681 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; | 1681 cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; |
1682 #endif | 1682 #endif |
1683 | 1683 |
1684 sv_frame_t startFrame = v->getStartFrame(); | 1684 sv_frame_t startFrame = v->getStartFrame(); |
1685 | 1685 |
1686 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1686 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1703 const View *view = v->getView(); | 1703 const View *view = v->getView(); |
1704 | 1704 |
1705 ImageCache &cache = m_imageCaches[view]; | 1705 ImageCache &cache = m_imageCaches[view]; |
1706 | 1706 |
1707 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1707 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1708 cerr << "SpectrogramLayer::paint(): image cache valid area " << cache. | 1708 cerr << "SpectrogramLayer::paint(): image cache valid area from " << cache.validArea.x() << "," << cache.validArea.y() << ", " << cache.validArea.width() << "x" << cache.validArea.height() << endl; |
1709 | |
1710 validArea.x() << ", " << cache.validArea.y() << ", " << cache.validArea.width() << "x" << cache.validArea.height() << endl; | |
1711 #endif | 1709 #endif |
1712 | 1710 |
1713 int zoomLevel = v->getZoomLevel(); | 1711 int zoomLevel = v->getZoomLevel(); |
1714 | 1712 |
1715 int x0 = 0; | 1713 int x0 = 0; |
1796 // and calculate its new valid area | 1794 // and calculate its new valid area |
1797 | 1795 |
1798 int px = cache.validArea.x(); | 1796 int px = cache.validArea.x(); |
1799 int pw = cache.validArea.width(); | 1797 int pw = cache.validArea.width(); |
1800 | 1798 |
1799 // so px and pw will be updated to the new x and | |
1800 // width of the valid area of cache; | |
1801 | |
1802 // x0 and x1 will be the left and right extents of | |
1803 // the area needing repainted | |
1804 | |
1805 px += dx; | |
1806 | |
1801 if (dx < 0) { | 1807 if (dx < 0) { |
1802 x0 = cw + dx; | 1808 // we scrolled left |
1803 x1 = cw; | |
1804 px += dx; | |
1805 if (px < 0) { | 1809 if (px < 0) { |
1806 pw += px; | 1810 pw += px; |
1807 px = 0; | 1811 px = 0; |
1808 if (pw < 0) pw = 0; | 1812 if (pw < 0) { |
1813 pw = 0; | |
1814 } | |
1809 } | 1815 } |
1810 } else { | 1816 x0 = px + pw; |
1811 x0 = 0; | 1817 x1 = cw; |
1812 x1 = dx; | 1818 } else { |
1813 px += dx; | 1819 // we scrolled right |
1814 if (px + pw > cw) { | 1820 if (px + pw > cw) { |
1815 pw = int(cw) - px; | 1821 pw = cw - px; |
1816 if (pw < 0) pw = 0; | 1822 if (pw < 0) { |
1823 pw = 0; | |
1824 } | |
1817 } | 1825 } |
1818 } | 1826 x0 = 0; |
1819 | 1827 x1 = px; |
1828 } | |
1829 | |
1820 cache.validArea = | 1830 cache.validArea = |
1821 QRect(px, cache.validArea.y(), | 1831 QRect(px, cache.validArea.y(), |
1822 pw, cache.validArea.height()); | 1832 pw, cache.validArea.height()); |
1823 | 1833 |
1824 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1834 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1825 cerr << "valid area now " | 1835 cerr << "SpectrogramLayer: valid area now " |
1826 << px << "," << cache.validArea.y() | 1836 << px << "," << cache.validArea.y() |
1827 << " " << pw << "x" << cache.validArea.height() | 1837 << " " << pw << "x" << cache.validArea.height() |
1828 << endl; | 1838 << endl; |
1829 #endif | 1839 #endif |
1830 | 1840 |
1832 | 1842 |
1833 // we've moved too far from the cached area for it | 1843 // we've moved too far from the cached area for it |
1834 // to be of use | 1844 // to be of use |
1835 | 1845 |
1836 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1846 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1837 cerr << "dx == " << dx << ": scrolled too far for cache to be useful" << endl; | 1847 cerr << "SpectrogramLayer: dx == " << dx << ": scrolled too far for cache to be useful" << endl; |
1838 #endif | 1848 #endif |
1839 | 1849 |
1840 cache.validArea = QRect(); | 1850 cache.validArea = QRect(); |
1841 recreateWholeImageCache = true; | 1851 recreateWholeImageCache = true; |
1842 } | 1852 } |
1871 // (further up in this function), but we want to ensure the cache | 1881 // (further up in this function), but we want to ensure the cache |
1872 // is coherent without having to worry about vertical matching of | 1882 // is coherent without having to worry about vertical matching of |
1873 // required and valid areas as well as horizontal. | 1883 // required and valid areas as well as horizontal. |
1874 | 1884 |
1875 int h = v->getPaintHeight(); | 1885 int h = v->getPaintHeight(); |
1876 | |
1877 /* | |
1878 auto mainPaintStart = chrono::steady_clock::now(); | |
1879 | |
1880 //!!! nb full-width case goes like | |
1881 paintBlockWidth = x1 - x0; | |
1882 | |
1883 if (cache.validArea.width() > 0) { | |
1884 | |
1885 // If part of the cache is known to be valid, select a strip | |
1886 // immediately to left or right of the valid part | |
1887 | |
1888 //!!! this really needs to be coordinated with the selection | |
1889 //!!! of m_drawBuffer boundaries in the bufferBinResolution | |
1890 //!!! case below | |
1891 | |
1892 int vx0 = 0, vx1 = 0; | |
1893 vx0 = cache.validArea.x(); | |
1894 vx1 = cache.validArea.x() + cache.validArea.width(); | |
1895 | |
1896 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1897 cerr << "x0 " << x0 << ", x1 " << x1 << ", vx0 " << vx0 << ", vx1 " << vx1 << endl; | |
1898 #endif | |
1899 if (x0 < vx0) { | |
1900 if (x0 + paintBlockWidth < vx0) { | |
1901 x0 = vx0 - paintBlockWidth; | |
1902 } | |
1903 x1 = vx0; | |
1904 } else if (x0 >= vx1) { | |
1905 x0 = vx1; | |
1906 if (x1 > x0 + paintBlockWidth) { | |
1907 x1 = x0 + paintBlockWidth; | |
1908 } | |
1909 } else { | |
1910 // x0 is within the valid area | |
1911 if (x1 > vx1) { | |
1912 x0 = vx1; | |
1913 if (x0 + paintBlockWidth < x1) { | |
1914 x1 = x0 + paintBlockWidth; | |
1915 } | |
1916 } else { | |
1917 x1 = x0; // it's all valid, paint nothing | |
1918 } | |
1919 } | |
1920 | |
1921 } else { | |
1922 if (x1 > x0 + paintBlockWidth) { | |
1923 int sfx = x1; | |
1924 if (startFrame < 0) sfx = v->getXForFrame(0); | |
1925 if (sfx >= x0 && sfx + paintBlockWidth <= x1) { | |
1926 x0 = sfx; | |
1927 x1 = x0 + paintBlockWidth; | |
1928 } else { | |
1929 int mid = (x1 + x0) / 2; | |
1930 x0 = mid - paintBlockWidth/2; | |
1931 x1 = x0 + paintBlockWidth; | |
1932 } | |
1933 } | |
1934 } | |
1935 */ | |
1936 | 1886 |
1937 int repaintWidth = x1 - x0; | 1887 int repaintWidth = x1 - x0; |
1938 | 1888 |
1939 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1889 // If we are painting a section to the left of a valid area of |
1940 cerr << "x0 " << x0 << ", x1 " << x1 | 1890 // cache, then we must paint it "backwards", right-to-left. This |
1941 << ", repaintWidth " << repaintWidth << ", h " << h << endl; | 1891 // is because painting may be interrupted by a timeout, leaving us |
1892 // with a partially painted area, and we have no way to record | |
1893 // that the union of the existing cached area and this new | |
1894 // partially painted bit is a valid cache area unless they are | |
1895 // adjacent (because our valid extent is a single x,width range). | |
1896 | |
1897 bool rightToLeft = (x0 == 0 && x1 < v->getPaintWidth()); | |
1898 | |
1899 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1900 cerr << "SpectrogramLayer: x0 " << x0 << ", x1 " << x1 | |
1901 << ", repaintWidth " << repaintWidth << ", h " << h | |
1902 << ", rightToLeft " << rightToLeft << endl; | |
1942 #endif | 1903 #endif |
1943 | 1904 |
1944 sv_samplerate_t sr = m_model->getSampleRate(); | 1905 sv_samplerate_t sr = m_model->getSampleRate(); |
1945 | 1906 |
1946 // Set minFreq and maxFreq to the frequency extents of the possibly | 1907 // Set minFreq and maxFreq to the frequency extents of the possibly |
1986 // cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << endl; | 1947 // cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << endl; |
1987 | 1948 |
1988 int increment = getWindowIncrement(); | 1949 int increment = getWindowIncrement(); |
1989 | 1950 |
1990 bool logarithmic = (m_frequencyScale == LogFrequencyScale); | 1951 bool logarithmic = (m_frequencyScale == LogFrequencyScale); |
1991 /* | 1952 |
1992 double yforbin[maxbin - minbin + 1]; | |
1993 | |
1994 for (int q = minbin; q <= maxbin; ++q) { | |
1995 double f0 = (double(q) * sr) / fftSize; | |
1996 yforbin[q - minbin] = | |
1997 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, | |
1998 logarithmic); | |
1999 } | |
2000 */ | |
2001 MagnitudeRange overallMag = m_viewMags[v]; | 1953 MagnitudeRange overallMag = m_viewMags[v]; |
2002 bool overallMagChanged = false; | 1954 bool overallMagChanged = false; |
2003 | 1955 |
2004 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1956 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2005 cerr << ((double(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; | 1957 cerr << "SpectrogramLayer: " << ((double(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; |
2006 #endif | 1958 #endif |
2007 | 1959 |
2008 if (repaintWidth == 0) { | 1960 if (repaintWidth == 0) { |
2009 SVDEBUG << "*** NOTE: repaintWidth == 0" << endl; | 1961 SVDEBUG << "*** NOTE: repaintWidth == 0" << endl; |
2010 } | 1962 } |
2072 bool usePeaksCache = false; | 2024 bool usePeaksCache = false; |
2073 | 2025 |
2074 if (bufferBinResolution) { | 2026 if (bufferBinResolution) { |
2075 for (int x = 0; x < bufwid; ++x) { | 2027 for (int x = 0; x < bufwid; ++x) { |
2076 binforx[x] = int(leftBoundaryFrame / increment) + x; | 2028 binforx[x] = int(leftBoundaryFrame / increment) + x; |
2077 // cerr << "binforx[" << x << "] = " << binforx[x] << endl; | |
2078 } | 2029 } |
2079 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); | 2030 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); |
2080 } else { | 2031 } else { |
2081 for (int x = 0; x < bufwid; ++x) { | 2032 for (int x = 0; x < bufwid; ++x) { |
2082 double s0 = 0, s1 = 0; | 2033 double s0 = 0, s1 = 0; |
2091 } | 2042 } |
2092 usePeaksCache = (increment * 8) < zoomLevel; | 2043 usePeaksCache = (increment * 8) < zoomLevel; |
2093 if (m_colourScale == PhaseColourScale) usePeaksCache = false; | 2044 if (m_colourScale == PhaseColourScale) usePeaksCache = false; |
2094 } | 2045 } |
2095 | 2046 |
2096 // No longer exists in Qt5: m_drawBuffer.setNumColors(256); | |
2097 for (int pixel = 0; pixel < 256; ++pixel) { | 2047 for (int pixel = 0; pixel < 256; ++pixel) { |
2098 m_drawBuffer.setColor((unsigned char)pixel, | 2048 m_drawBuffer.setColor((unsigned char)pixel, |
2099 m_palette.getColour((unsigned char)pixel).rgb()); | 2049 m_palette.getColour((unsigned char)pixel).rgb()); |
2100 } | 2050 } |
2101 | 2051 |
2112 binfory[y] = q0; | 2062 binfory[y] = q0; |
2113 } | 2063 } |
2114 } | 2064 } |
2115 | 2065 |
2116 attainedBufwid = | 2066 attainedBufwid = |
2117 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache, | 2067 paintDrawBuffer(v, bufwid, h, binforx, binfory, |
2118 overallMag, overallMagChanged); | 2068 usePeaksCache, |
2069 overallMag, overallMagChanged, | |
2070 rightToLeft); | |
2119 | 2071 |
2120 } else { | 2072 } else { |
2121 | 2073 |
2122 attainedBufwid = | 2074 attainedBufwid = |
2123 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx, | 2075 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx, |
2124 minbin, maxbin, | 2076 minbin, maxbin, |
2125 displayMinFreq, displayMaxFreq, | 2077 displayMinFreq, displayMaxFreq, |
2126 logarithmic, | 2078 logarithmic, |
2127 overallMag, overallMagChanged); | 2079 overallMag, overallMagChanged, |
2080 rightToLeft); | |
2128 } | 2081 } |
2129 | 2082 |
2130 int failedToRepaint = bufwid - attainedBufwid; | 2083 int failedToRepaint = bufwid - attainedBufwid; |
2131 if (failedToRepaint > 0) { | 2084 if (failedToRepaint > 0) { |
2132 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2085 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2133 cerr << "Failed to repaint " << failedToRepaint << " of " << bufwid | 2086 cerr << "SpectrogramLayer::paint(): Failed to repaint " << failedToRepaint << " of " << bufwid |
2134 << " columns in time" << endl; | 2087 << " columns in time" << endl; |
2135 #endif | 2088 #endif |
2136 } else if (failedToRepaint < 0) { | 2089 } else if (failedToRepaint < 0) { |
2137 cerr << "WARNING: failedToRepaint < 0 (= " << failedToRepaint << ")" | 2090 cerr << "WARNING: failedToRepaint < 0 (= " << failedToRepaint << ")" |
2138 << endl; | 2091 << endl; |
2140 } | 2093 } |
2141 | 2094 |
2142 if (overallMagChanged) { | 2095 if (overallMagChanged) { |
2143 m_viewMags[v] = overallMag; | 2096 m_viewMags[v] = overallMag; |
2144 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2097 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2145 cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << endl; | 2098 cerr << "SpectrogramLayer: Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << endl; |
2146 #endif | 2099 #endif |
2147 } | 2100 } |
2148 | 2101 |
2149 outerprof.end(); | 2102 outerprof.end(); |
2150 | 2103 |
2151 Profiler profiler2("SpectrogramLayer::paint: draw image"); | 2104 Profiler profiler2("SpectrogramLayer::paint: draw image"); |
2152 | 2105 |
2153 if (recreateWholeImageCache) { | 2106 if (recreateWholeImageCache) { |
2154 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2107 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2155 cerr << "Recreating image cache: width = " << v->getPaintWidth() | 2108 cerr << "SpectrogramLayer: Recreating image cache: width = " << v->getPaintWidth() |
2156 << ", height = " << h << endl; | 2109 << ", height = " << h << endl; |
2157 #endif | 2110 #endif |
2158 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied); | 2111 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied); |
2159 } | 2112 } |
2160 | 2113 |
2161 if (repaintWidth > 0) { | 2114 if (repaintWidth > 0) { |
2162 | 2115 |
2163 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2116 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2164 cerr << "Painting " << repaintWidth << "x" << h | 2117 cerr << "SpectrogramLayer: Copying " << repaintWidth << "x" << h |
2165 << " from draw buffer at " << 0 << "," << 0 | 2118 << " from draw buffer at " << 0 << "," << 0 |
2166 << " to " << repaintWidth << "x" << h << " on cache at " | 2119 << " to " << repaintWidth << "x" << h << " on cache at " |
2167 << x0 << "," << 0 << endl; | 2120 << x0 << "," << 0 << endl; |
2168 #endif | 2121 #endif |
2169 | 2122 |
2171 | 2124 |
2172 if (bufferBinResolution) { | 2125 if (bufferBinResolution) { |
2173 int scaledLeft = v->getXForFrame(leftBoundaryFrame); | 2126 int scaledLeft = v->getXForFrame(leftBoundaryFrame); |
2174 int scaledRight = v->getXForFrame(rightBoundaryFrame); | 2127 int scaledRight = v->getXForFrame(rightBoundaryFrame); |
2175 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2128 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2176 cerr << "Rescaling image from " << bufwid | 2129 cerr << "SpectrogramLayer: Rescaling image from " << bufwid |
2177 << "x" << h << " to " | 2130 << "x" << h << " to " |
2178 << scaledRight-scaledLeft << "x" << h << endl; | 2131 << scaledRight-scaledLeft << "x" << h << endl; |
2179 #endif | 2132 #endif |
2180 Preferences::SpectrogramXSmoothing xsmoothing = | 2133 Preferences::SpectrogramXSmoothing xsmoothing = |
2181 Preferences::getInstance()->getSpectrogramXSmoothing(); | 2134 Preferences::getInstance()->getSpectrogramXSmoothing(); |
2182 // SVDEBUG << "xsmoothing == " << xsmoothing << endl; | 2135 |
2183 QImage scaled = m_drawBuffer.scaled | 2136 QImage scaled = m_drawBuffer.scaled |
2184 (scaledRight - scaledLeft, h, | 2137 (scaledRight - scaledLeft, h, |
2185 Qt::IgnoreAspectRatio, | 2138 Qt::IgnoreAspectRatio, |
2186 ((xsmoothing == Preferences::SpectrogramXInterpolated) ? | 2139 ((xsmoothing == Preferences::SpectrogramXInterpolated) ? |
2187 Qt::SmoothTransformation : Qt::FastTransformation)); | 2140 Qt::SmoothTransformation : Qt::FastTransformation)); |
2141 | |
2188 int scaledLeftCrop = v->getXForFrame(leftCropFrame); | 2142 int scaledLeftCrop = v->getXForFrame(leftCropFrame); |
2189 int scaledRightCrop = v->getXForFrame(rightCropFrame); | 2143 int scaledRightCrop = v->getXForFrame(rightCropFrame); |
2190 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2144 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2191 cerr << "Drawing image region of width " << scaledRightCrop - scaledLeftCrop << " to " | 2145 cerr << "SpectrogramLayer: Drawing image region of width " << scaledRightCrop - scaledLeftCrop << " to " |
2192 << scaledLeftCrop << " from " << scaledLeftCrop - scaledLeft << endl; | 2146 << scaledLeftCrop << " from " << scaledLeftCrop - scaledLeft << endl; |
2193 #endif | 2147 #endif |
2194 cachePainter.drawImage | 2148 cachePainter.drawImage |
2195 (QRect(scaledLeftCrop, 0, | 2149 (QRect(scaledLeftCrop, 0, |
2196 scaledRightCrop - scaledLeftCrop, h), | 2150 scaledRightCrop - scaledLeftCrop, h), |
2207 | 2161 |
2208 cachePainter.end(); | 2162 cachePainter.end(); |
2209 } | 2163 } |
2210 | 2164 |
2211 // update cache valid area based on painted area | 2165 // update cache valid area based on painted area |
2212 if (cache.validArea.width() > 0) { | |
2213 | 2166 |
2214 int left = min(cache.validArea.x(), x0); | 2167 int left = min(cache.validArea.x(), x0); |
2215 | 2168 |
2216 int wid = max(cache.validArea.x() + cache.validArea.width() - left, | 2169 if (cache.validArea.width() == 0) { |
2217 x1 - left); | 2170 left = 0; // cache was not valid at all |
2218 wid = wid - failedToRepaint; | 2171 } |
2172 | |
2173 int wid = max(cache.validArea.x() + cache.validArea.width() - left, | |
2174 x1 - left); | |
2175 | |
2176 if (failedToRepaint > 0) { | |
2177 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2178 cerr << "SpectrogramLayer: Reduced painted extent from " | |
2179 << left << "," << wid; | |
2180 #endif | |
2181 if (rightToLeft) { | |
2182 left += failedToRepaint; | |
2183 } | |
2184 wid -= failedToRepaint; | |
2185 | |
2219 if (wid < 0) wid = 0; | 2186 if (wid < 0) wid = 0; |
2220 | 2187 |
2221 cache.validArea = QRect | 2188 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2222 (left, cache.validArea.y(), wid, cache.validArea.height()); | 2189 cerr << " to " << left << "," << wid << endl; |
2223 | 2190 #endif |
2224 } else { | 2191 } |
2225 | 2192 |
2226 int wid = x1 - x0; | 2193 cache.validArea = QRect(left, 0, wid, h); |
2227 wid = wid - failedToRepaint; | 2194 |
2228 if (wid < 0) wid = 0; | 2195 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2229 | 2196 cerr << "SpectrogramLayer: Cache valid area becomes " << cache.validArea.x() |
2230 cache.validArea = QRect(x0, 0, wid, h); | |
2231 } | |
2232 | |
2233 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2234 cerr << "Cache valid area becomes " << cache.validArea.x() | |
2235 << ", " << cache.validArea.y() << ", " | 2197 << ", " << cache.validArea.y() << ", " |
2236 << cache.validArea.width() << "x" | 2198 << cache.validArea.width() << "x" |
2237 << cache.validArea.height() << endl; | 2199 << cache.validArea.height() << endl; |
2238 #endif | 2200 #endif |
2239 | 2201 |
2240 QRect pr = rect & cache.validArea; | 2202 QRect pr = rect & cache.validArea; |
2241 | 2203 |
2242 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2204 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2243 cerr << "Painting " << pr.width() << "x" << pr.height() | 2205 cerr << "SpectrogramLayer: Copying " << pr.width() << "x" << pr.height() |
2244 << " from cache at " << pr.x() << "," << pr.y() | 2206 << " from cache at " << pr.x() << "," << pr.y() |
2245 << " to window" << endl; | 2207 << " to window" << endl; |
2246 #endif | 2208 #endif |
2247 | 2209 |
2248 paint.drawImage(pr.x(), pr.y(), cache.image, | 2210 paint.drawImage(pr.x(), pr.y(), cache.image, |
2291 illuminateLocalFeatures(v, paint); | 2253 illuminateLocalFeatures(v, paint); |
2292 | 2254 |
2293 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2255 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2294 cerr << "SpectrogramLayer::paint() returning" << endl; | 2256 cerr << "SpectrogramLayer::paint() returning" << endl; |
2295 #endif | 2257 #endif |
2296 /*!!! | |
2297 if (!m_synchronous) { | |
2298 auto mainPaintEnd = chrono::steady_clock::now(); | |
2299 auto diff = mainPaintEnd - mainPaintStart; | |
2300 m_lastPaintTime = chrono::duration<double>(diff).count(); | |
2301 } | |
2302 */ | |
2303 } | 2258 } |
2304 | 2259 |
2305 int | 2260 int |
2306 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, | 2261 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, |
2307 int w, | 2262 int w, |
2311 int maxbin, | 2266 int maxbin, |
2312 double displayMinFreq, | 2267 double displayMinFreq, |
2313 double displayMaxFreq, | 2268 double displayMaxFreq, |
2314 bool logarithmic, | 2269 bool logarithmic, |
2315 MagnitudeRange &overallMag, | 2270 MagnitudeRange &overallMag, |
2316 bool &overallMagChanged) const | 2271 bool &overallMagChanged, |
2272 bool rightToLeft) const | |
2317 { | 2273 { |
2318 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies"); | 2274 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies"); |
2319 | 2275 |
2320 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2276 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2321 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; | 2277 cerr << "SpectrogramLayer::paintDrawBufferPeakFrequencies: minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; |
2322 #endif | 2278 #endif |
2323 if (minbin < 0) minbin = 0; | 2279 if (minbin < 0) minbin = 0; |
2324 if (maxbin < 0) maxbin = minbin+1; | 2280 if (maxbin < 0) maxbin = minbin+1; |
2325 | 2281 |
2326 FFTModel *fft = getFFTModel(v); | 2282 FFTModel *fft = getFFTModel(v); |
2334 float values[maxbin - minbin + 1]; | 2290 float values[maxbin - minbin + 1]; |
2335 #else | 2291 #else |
2336 float *values = (float *)alloca((maxbin - minbin + 1) * sizeof(float)); | 2292 float *values = (float *)alloca((maxbin - minbin + 1) * sizeof(float)); |
2337 #endif | 2293 #endif |
2338 | 2294 |
2339 for (int x = 0; x < w; ++x) { | 2295 int start = 0; |
2296 int finish = w; | |
2297 int step = 1; | |
2298 | |
2299 if (rightToLeft) { | |
2300 start = w-1; | |
2301 finish = -1; | |
2302 step = -1; | |
2303 } | |
2304 | |
2305 for (int x = start; x != finish; x += step) { | |
2340 | 2306 |
2341 if (binforx[x] < 0) continue; | 2307 if (binforx[x] < 0) continue; |
2342 | 2308 |
2343 int sx0 = binforx[x]; | 2309 int sx0 = binforx[x]; |
2344 int sx1 = sx0; | 2310 int sx1 = sx0; |
2427 int h, | 2393 int h, |
2428 const vector<int> &binforx, | 2394 const vector<int> &binforx, |
2429 const vector<double> &binfory, | 2395 const vector<double> &binfory, |
2430 bool usePeaksCache, | 2396 bool usePeaksCache, |
2431 MagnitudeRange &overallMag, | 2397 MagnitudeRange &overallMag, |
2432 bool &overallMagChanged) const | 2398 bool &overallMagChanged, |
2399 bool rightToLeft) const | |
2433 { | 2400 { |
2434 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); | 2401 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); |
2435 | 2402 |
2436 //!!! todo: propagate to paintDrawBufferPeakFrequencies | 2403 //!!! todo: propagate to paintDrawBufferPeakFrequencies |
2437 | 2404 |
2442 | 2409 |
2443 int minbin = int(binfory[0] + 0.0001); | 2410 int minbin = int(binfory[0] + 0.0001); |
2444 int maxbin = int(binfory[h-1]); | 2411 int maxbin = int(binfory[h-1]); |
2445 | 2412 |
2446 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2413 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2447 cerr << "paintDrawBuffer: minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; | 2414 cerr << "SpectrogramLayer::paintDrawBuffer: minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; |
2448 #endif | 2415 #endif |
2449 if (minbin < 0) minbin = 0; | 2416 if (minbin < 0) minbin = 0; |
2450 if (maxbin < 0) maxbin = minbin+1; | 2417 if (maxbin < 0) maxbin = minbin+1; |
2451 | 2418 |
2452 DenseThreeDimensionalModel *sourceModel = 0; | 2419 DenseThreeDimensionalModel *sourceModel = 0; |
2453 FFTModel *fft = 0; | 2420 FFTModel *fft = 0; |
2454 int divisor = 1; | 2421 int divisor = 1; |
2455 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2422 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2456 cerr << "Note: bin display = " << m_binDisplay << ", w = " << w << ", binforx[" << w-1 << "] = " << binforx[w-1] << ", binforx[0] = " << binforx[0] << endl; | 2423 cerr << "SpectrogramLayer::paintDrawBuffer: Note: bin display = " << m_binDisplay << ", w = " << w << ", binforx[" << w-1 << "] = " << binforx[w-1] << ", binforx[0] = " << binforx[0] << endl; |
2457 #endif | 2424 #endif |
2458 if (usePeaksCache) { //!!! | 2425 if (usePeaksCache) { //!!! |
2459 sourceModel = getPeakCache(v); | 2426 sourceModel = getPeakCache(v); |
2460 divisor = 8;//!!! | 2427 divisor = 8;//!!! |
2461 minbin = 0; | 2428 minbin = 0; |
2488 #endif | 2455 #endif |
2489 | 2456 |
2490 const float *values = autoarray; | 2457 const float *values = autoarray; |
2491 DenseThreeDimensionalModel::Column c; | 2458 DenseThreeDimensionalModel::Column c; |
2492 | 2459 |
2493 for (int x = 0; x < w; ++x) { | 2460 int start = 0; |
2461 int finish = w; | |
2462 int step = 1; | |
2463 | |
2464 if (rightToLeft) { | |
2465 start = w-1; | |
2466 finish = -1; | |
2467 step = -1; | |
2468 } | |
2469 | |
2470 for (int x = start; x != finish; x += step) { | |
2494 | 2471 |
2495 if (binforx[x] < 0) continue; | 2472 if (binforx[x] < 0) continue; |
2496 | 2473 |
2497 // float columnGain = m_gain; | 2474 // float columnGain = m_gain; |
2498 float columnMax = 0.f; | 2475 float columnMax = 0.f; |
2517 MagnitudeRange mag; | 2494 MagnitudeRange mag; |
2518 | 2495 |
2519 if (sx != psx) { | 2496 if (sx != psx) { |
2520 if (fft) { | 2497 if (fft) { |
2521 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2498 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2522 cerr << "Retrieving column " << sx << " from fft directly" << endl; | 2499 // cerr << "Retrieving column " << sx << " from fft directly" << endl; |
2523 #endif | 2500 #endif |
2524 if (m_colourScale == PhaseColourScale) { | 2501 if (m_colourScale == PhaseColourScale) { |
2525 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2502 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2526 } else if (m_normalization == NormalizeColumns) { | 2503 } else if (m_normalization == NormalizeColumns) { |
2527 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2504 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2536 } else { | 2513 } else { |
2537 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2514 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2538 } | 2515 } |
2539 } else { | 2516 } else { |
2540 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2517 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2541 cerr << "Retrieving column " << sx << " from peaks cache" << endl; | 2518 // cerr << "Retrieving column " << sx << " from peaks cache" << endl; |
2542 #endif | 2519 #endif |
2543 c = sourceModel->getColumn(sx); | 2520 c = sourceModel->getColumn(sx); |
2544 if (m_normalization == NormalizeColumns || | 2521 if (m_normalization == NormalizeColumns || |
2545 m_normalization == NormalizeHybrid) { | 2522 m_normalization == NormalizeHybrid) { |
2546 for (int y = 0; y < h; ++y) { | 2523 for (int y = 0; y < h; ++y) { |
2664 if (x >= minColumns) { | 2641 if (x >= minColumns) { |
2665 auto t = chrono::steady_clock::now(); | 2642 auto t = chrono::steady_clock::now(); |
2666 double diff = chrono::duration<double>(t - startTime).count(); | 2643 double diff = chrono::duration<double>(t - startTime).count(); |
2667 if (diff > maxTime) { | 2644 if (diff > maxTime) { |
2668 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2645 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2669 cerr << "Max time " << maxTime << " sec exceeded after " | 2646 cerr << "SpectrogramLayer::paintDrawBuffer: Max time " << maxTime << " sec exceeded after " |
2670 << x << " columns with time " << diff << endl; | 2647 << x << " columns with time " << diff << endl; |
2671 #endif | 2648 #endif |
2672 return x; | 2649 return x; |
2673 } | 2650 } |
2674 } | 2651 } |