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 }