comparison layer/SpectrogramLayer.cpp @ 1039:bfce7940c017 spectrogram-minor-refactor

Don't use partial paints when zoomed in far enough to have boundary alignment concerns. (But boundary calculations are still wrong, leading to a logic error exception.)
author Chris Cannam
date Tue, 02 Feb 2016 16:00:31 +0000
parents 6d4fa45a271d
children 25b035362c44
comparison
equal deleted inserted replaced
1038:6d4fa45a271d 1039:bfce7940c017
1853 // If (getFrameForX(x) / increment) * increment == 1853 // If (getFrameForX(x) / increment) * increment ==
1854 // getFrameForX(x), then x is a time-bin boundary. We want two 1854 // getFrameForX(x), then x is a time-bin boundary. We want two
1855 // such boundaries at either side of the draw buffer -- one which 1855 // such boundaries at either side of the draw buffer -- one which
1856 // we draw up to, and one which we subsequently crop at. 1856 // we draw up to, and one which we subsequently crop at.
1857 1857
1858 bool bufferBinResolution = false; 1858 bool bufferIsBinResolution = false;
1859 if (increment > zoomLevel) bufferBinResolution = true; 1859 if (increment > zoomLevel) bufferIsBinResolution = true;
1860 1860
1861 sv_frame_t leftBoundaryFrame = -1, leftCropFrame = -1; 1861 sv_frame_t leftBoundaryFrame = -1, leftCropFrame = -1;
1862 sv_frame_t rightBoundaryFrame = -1, rightCropFrame = -1; 1862 sv_frame_t rightBoundaryFrame = -1, rightCropFrame = -1;
1863 1863
1864 int bufwid; 1864 int bufwid;
1865 1865
1866 if (bufferBinResolution) { 1866 if (bufferIsBinResolution) {
1867 1867
1868 for (int x = x0; ; --x) { 1868 for (int x = x0; ; --x) {
1869 sv_frame_t f = v->getFrameForX(x); 1869 sv_frame_t f = v->getFrameForX(x);
1870 if ((f / increment) * increment == f) { 1870 if ((f / increment) * increment == f) {
1871 if (leftCropFrame == -1) leftCropFrame = f; 1871 if (leftCropFrame == -1) leftCropFrame = f;
1900 vector<int> binforx(bufwid); 1900 vector<int> binforx(bufwid);
1901 vector<double> binfory(h); 1901 vector<double> binfory(h);
1902 1902
1903 bool usePeaksCache = false; 1903 bool usePeaksCache = false;
1904 1904
1905 if (bufferBinResolution) { 1905 if (bufferIsBinResolution) {
1906 for (int x = 0; x < bufwid; ++x) { 1906 for (int x = 0; x < bufwid; ++x) {
1907 binforx[x] = int(leftBoundaryFrame / increment) + x; 1907 binforx[x] = int(leftBoundaryFrame / increment) + x;
1908 } 1908 }
1909 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); 1909 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8);
1910 } else { 1910 } else {
1928 m_palette.getColour((unsigned char)pixel).rgb()); 1928 m_palette.getColour((unsigned char)pixel).rgb());
1929 } 1929 }
1930 1930
1931 m_drawBuffer.fill(0); 1931 m_drawBuffer.fill(0);
1932 int attainedBufwid = bufwid; 1932 int attainedBufwid = bufwid;
1933 1933
1934 double softTimeLimit;
1935
1936 if (m_synchronous) {
1937
1938 // must paint the whole thing for synchronous mode, so give
1939 // "no timeout"
1940 softTimeLimit = 0.0;
1941
1942 } else if (bufferIsBinResolution) {
1943
1944 // calculating boundaries later will be too fiddly for partial
1945 // paints, and painting should be fast anyway when this is the
1946 // case because it means we're well zoomed in
1947 softTimeLimit = 0.0;
1948
1949 } else {
1950
1951 // neither limitation applies, so use a short soft limit
1952
1953 if (m_binDisplay == PeakFrequencies) {
1954 softTimeLimit = 0.15;
1955 } else {
1956 softTimeLimit = 0.1;
1957 }
1958 }
1959
1934 if (m_binDisplay != PeakFrequencies) { 1960 if (m_binDisplay != PeakFrequencies) {
1935 1961
1936 for (int y = 0; y < h; ++y) { 1962 for (int y = 0; y < h; ++y) {
1937 double q0 = 0, q1 = 0; 1963 double q0 = 0, q1 = 0;
1938 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) { 1964 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) {
1944 1970
1945 attainedBufwid = 1971 attainedBufwid =
1946 paintDrawBuffer(v, bufwid, h, binforx, binfory, 1972 paintDrawBuffer(v, bufwid, h, binforx, binfory,
1947 usePeaksCache, 1973 usePeaksCache,
1948 overallMag, overallMagChanged, 1974 overallMag, overallMagChanged,
1949 rightToLeft); 1975 rightToLeft,
1976 softTimeLimit);
1950 1977
1951 } else { 1978 } else {
1952 1979
1953 attainedBufwid = 1980 attainedBufwid =
1954 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx, 1981 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx,
1955 minbin, maxbin, 1982 minbin, maxbin,
1956 displayMinFreq, displayMaxFreq, 1983 displayMinFreq, displayMaxFreq,
1957 logarithmic, 1984 logarithmic,
1958 overallMag, overallMagChanged, 1985 overallMag, overallMagChanged,
1959 rightToLeft); 1986 rightToLeft,
1987 softTimeLimit);
1960 } 1988 }
1961 1989
1962 int failedToRepaint = bufwid - attainedBufwid; 1990 int failedToRepaint = bufwid - attainedBufwid;
1963 1991
1964 int paintedLeft = x0; 1992 int paintedLeft = x0;
2005 << " from draw buffer at " << paintedLeft - x0 << "," << 0 2033 << " from draw buffer at " << paintedLeft - x0 << "," << 0
2006 << " to " << paintedWidth << "x" << h << " on cache at " 2034 << " to " << paintedWidth << "x" << h << " on cache at "
2007 << x0 << "," << 0 << endl; 2035 << x0 << "," << 0 << endl;
2008 #endif 2036 #endif
2009 2037
2010 if (bufferBinResolution) { 2038 if (bufferIsBinResolution) {
2011 2039
2012 int scaledLeft = v->getXForFrame(leftBoundaryFrame); 2040 int scaledLeft = v->getXForFrame(leftBoundaryFrame);
2013 int scaledRight = v->getXForFrame(rightBoundaryFrame); 2041 int scaledRight = v->getXForFrame(rightBoundaryFrame);
2014 2042
2015 #ifdef DEBUG_SPECTROGRAM_REPAINT 2043 #ifdef DEBUG_SPECTROGRAM_REPAINT
2136 double displayMinFreq, 2164 double displayMinFreq,
2137 double displayMaxFreq, 2165 double displayMaxFreq,
2138 bool logarithmic, 2166 bool logarithmic,
2139 MagnitudeRange &overallMag, 2167 MagnitudeRange &overallMag,
2140 bool &overallMagChanged, 2168 bool &overallMagChanged,
2141 bool rightToLeft) const 2169 bool rightToLeft,
2170 double softTimeLimit) const
2142 { 2171 {
2143 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies"); 2172 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies");
2144 2173
2145 #ifdef DEBUG_SPECTROGRAM_REPAINT 2174 #ifdef DEBUG_SPECTROGRAM_REPAINT
2146 cerr << "SpectrogramLayer::paintDrawBufferPeakFrequencies: minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; 2175 cerr << "SpectrogramLayer::paintDrawBufferPeakFrequencies: minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl;
2160 #else 2189 #else
2161 float *values = (float *)alloca((maxbin - minbin + 1) * sizeof(float)); 2190 float *values = (float *)alloca((maxbin - minbin + 1) * sizeof(float));
2162 #endif 2191 #endif
2163 2192
2164 int minColumns = 4; 2193 int minColumns = 4;
2165 double softTimeLimit = 0.15; // seconds; only for non-synchronous drawing 2194 bool haveTimeLimits = (softTimeLimit > 0.0);
2166 double hardTimeLimit = softTimeLimit * 2.0; 2195 double hardTimeLimit = softTimeLimit * 2.0;
2167 bool overridingSoftLimit = false; 2196 bool overridingSoftLimit = false;
2168 auto startTime = chrono::steady_clock::now(); 2197 auto startTime = chrono::steady_clock::now();
2169 2198
2170 int start = 0; 2199 int start = 0;
2260 if (overallMag.sample(mag)) overallMagChanged = true; 2289 if (overallMag.sample(mag)) overallMagChanged = true;
2261 } 2290 }
2262 } 2291 }
2263 } 2292 }
2264 2293
2265 if (!m_synchronous) { 2294 if (haveTimeLimits) {
2266 if (columnCount >= minColumns) { 2295 if (columnCount >= minColumns) {
2267 auto t = chrono::steady_clock::now(); 2296 auto t = chrono::steady_clock::now();
2268 double diff = chrono::duration<double>(t - startTime).count(); 2297 double diff = chrono::duration<double>(t - startTime).count();
2269 if (diff > hardTimeLimit) { 2298 if (diff > hardTimeLimit) {
2270 #ifdef DEBUG_SPECTROGRAM_REPAINT 2299 #ifdef DEBUG_SPECTROGRAM_REPAINT
2301 const vector<int> &binforx, 2330 const vector<int> &binforx,
2302 const vector<double> &binfory, 2331 const vector<double> &binfory,
2303 bool usePeaksCache, 2332 bool usePeaksCache,
2304 MagnitudeRange &overallMag, 2333 MagnitudeRange &overallMag,
2305 bool &overallMagChanged, 2334 bool &overallMagChanged,
2306 bool rightToLeft) const 2335 bool rightToLeft,
2336 double softTimeLimit) const
2307 { 2337 {
2308 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); 2338 Profiler profiler("SpectrogramLayer::paintDrawBuffer");
2309 2339
2310 int minbin = int(binfory[0] + 0.0001); 2340 int minbin = int(binfory[0] + 0.0001);
2311 int maxbin = int(binfory[h-1]); 2341 int maxbin = int(binfory[h-1]);
2356 2386
2357 const float *values = autoarray; 2387 const float *values = autoarray;
2358 DenseThreeDimensionalModel::Column c; 2388 DenseThreeDimensionalModel::Column c;
2359 2389
2360 int minColumns = 4; 2390 int minColumns = 4;
2361 double softTimeLimit = 0.1; // seconds; only for non-synchronous drawing 2391 bool haveTimeLimits = (softTimeLimit > 0.0);
2362 double hardTimeLimit = softTimeLimit * 2.0; 2392 double hardTimeLimit = softTimeLimit * 2.0;
2363 bool overridingSoftLimit = false; 2393 bool overridingSoftLimit = false;
2364 auto startTime = chrono::steady_clock::now(); 2394 auto startTime = chrono::steady_clock::now();
2365 2395
2366 int start = 0; 2396 int start = 0;
2545 unsigned char peakpix = getDisplayValue(v, peak); 2575 unsigned char peakpix = getDisplayValue(v, peak);
2546 2576
2547 m_drawBuffer.setPixel(x, h-y-1, peakpix); 2577 m_drawBuffer.setPixel(x, h-y-1, peakpix);
2548 } 2578 }
2549 2579
2550 if (!m_synchronous) { 2580 if (haveTimeLimits) {
2551 if (columnCount >= minColumns) { 2581 if (columnCount >= minColumns) {
2552 auto t = chrono::steady_clock::now(); 2582 auto t = chrono::steady_clock::now();
2553 double diff = chrono::duration<double>(t - startTime).count(); 2583 double diff = chrono::duration<double>(t - startTime).count();
2554 if (diff > hardTimeLimit) { 2584 if (diff > hardTimeLimit) {
2555 #ifdef DEBUG_SPECTROGRAM_REPAINT 2585 #ifdef DEBUG_SPECTROGRAM_REPAINT