Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 1024:3bce4c45b681 spectrogram-minor-refactor
Rearrange cache update calculations so as to use the actual painted width returned by paint functions (though they only ever return the same width as requested, at this point)
| author | Chris Cannam | 
|---|---|
| date | Mon, 25 Jan 2016 15:52:26 +0000 | 
| parents | 74755fa6ea9e | 
| children | c02de0e34233 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 1023:74755fa6ea9e | 1024:3bce4c45b681 | 
|---|---|
| 1952 } | 1952 } | 
| 1953 } else { | 1953 } else { | 
| 1954 x1 = x0; // it's all valid, paint nothing | 1954 x1 = x0; // it's all valid, paint nothing | 
| 1955 } | 1955 } | 
| 1956 } | 1956 } | 
| 1957 | |
| 1958 cache.validArea = QRect | |
| 1959 (std::min(vx0, x0), cache.validArea.y(), | |
| 1960 std::max(vx1 - std::min(vx0, x0), | |
| 1961 x1 - std::min(vx0, x0)), | |
| 1962 cache.validArea.height()); | |
| 1963 | |
| 1964 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
| 1965 cerr << "Valid area becomes " << cache.validArea.x() | |
| 1966 << ", " << cache.validArea.y() << ", " | |
| 1967 << cache.validArea.width() << "x" | |
| 1968 << cache.validArea.height() << endl; | |
| 1969 #endif | |
| 1970 | 1957 | 
| 1971 } else { | 1958 } else { | 
| 1972 if (x1 > x0 + paintBlockWidth) { | 1959 if (x1 > x0 + paintBlockWidth) { | 
| 1973 int sfx = x1; | 1960 int sfx = x1; | 
| 1974 if (startFrame < 0) sfx = v->getXForFrame(0); | 1961 if (startFrame < 0) sfx = v->getXForFrame(0); | 
| 1979 int mid = (x1 + x0) / 2; | 1966 int mid = (x1 + x0) / 2; | 
| 1980 x0 = mid - paintBlockWidth/2; | 1967 x0 = mid - paintBlockWidth/2; | 
| 1981 x1 = x0 + paintBlockWidth; | 1968 x1 = x0 + paintBlockWidth; | 
| 1982 } | 1969 } | 
| 1983 } | 1970 } | 
| 1984 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1971 } | 
| 1985 cerr << "Valid area becomes " << x0 << ", 0, " << (x1-x0) | 1972 | 
| 1986 << "x" << h << endl; | 1973 int repaintWidth = x1 - x0; | 
| 1987 #endif | |
| 1988 cache.validArea = QRect(x0, 0, x1 - x0, h); | |
| 1989 } | |
| 1990 | |
| 1991 /* | |
| 1992 if (xPixelRatio != 1.f) { | |
| 1993 x0 = int((int(x0 / xPixelRatio) - 4) * xPixelRatio + 0.0001); | |
| 1994 x1 = int((int(x1 / xPixelRatio) + 4) * xPixelRatio + 0.0001); | |
| 1995 } | |
| 1996 */ | |
| 1997 int w = x1 - x0; | |
| 1998 | 1974 | 
| 1999 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1975 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2000 cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << endl; | 1976 cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << endl; | 
| 2001 #endif | 1977 #endif | 
| 2002 | 1978 | 
| 2062 | 2038 | 
| 2063 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2039 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2064 cerr << ((double(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; | 2040 cerr << ((double(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; | 
| 2065 #endif | 2041 #endif | 
| 2066 | 2042 | 
| 2067 if (w == 0) { | 2043 if (repaintWidth == 0) { | 
| 2068 SVDEBUG << "*** NOTE: w == 0" << endl; | 2044 SVDEBUG << "*** NOTE: repaintWidth == 0" << endl; | 
| 2069 } | 2045 } | 
| 2070 | 2046 | 
| 2071 Profiler outerprof("SpectrogramLayer::paint: all cols"); | 2047 Profiler outerprof("SpectrogramLayer::paint: all cols"); | 
| 2072 | 2048 | 
| 2073 // The draw buffer contains a fragment at either our pixel | 2049 // The draw buffer contains a fragment at either our pixel | 
| 2095 | 2071 | 
| 2096 for (int x = x0; ; --x) { | 2072 for (int x = x0; ; --x) { | 
| 2097 sv_frame_t f = v->getFrameForX(x); | 2073 sv_frame_t f = v->getFrameForX(x); | 
| 2098 if ((f / increment) * increment == f) { | 2074 if ((f / increment) * increment == f) { | 
| 2099 if (leftCropFrame == -1) leftCropFrame = f; | 2075 if (leftCropFrame == -1) leftCropFrame = f; | 
| 2100 else if (x < x0 - 2) { leftBoundaryFrame = f; break; } | 2076 else if (x < x0 - 2) { | 
| 2077 leftBoundaryFrame = f; | |
| 2078 break; | |
| 2079 } | |
| 2101 } | 2080 } | 
| 2102 } | 2081 } | 
| 2103 for (int x = x0 + w; ; ++x) { | 2082 for (int x = x0 + repaintWidth; ; ++x) { | 
| 2104 sv_frame_t f = v->getFrameForX(x); | 2083 sv_frame_t f = v->getFrameForX(x); | 
| 2105 if ((f / increment) * increment == f) { | 2084 if ((f / increment) * increment == f) { | 
| 2106 if (rightCropFrame == -1) rightCropFrame = f; | 2085 if (rightCropFrame == -1) rightCropFrame = f; | 
| 2107 else if (x > x0 + w + 2) { rightBoundaryFrame = f; break; } | 2086 else if (x > x0 + repaintWidth + 2) { | 
| 2087 rightBoundaryFrame = f; | |
| 2088 break; | |
| 2089 } | |
| 2108 } | 2090 } | 
| 2109 } | 2091 } | 
| 2110 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2092 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2111 cerr << "Left: crop: " << leftCropFrame << " (bin " << leftCropFrame/increment << "); boundary: " << leftBoundaryFrame << " (bin " << leftBoundaryFrame/increment << ")" << endl; | 2093 cerr << "Left: crop: " << leftCropFrame << " (bin " << leftCropFrame/increment << "); boundary: " << leftBoundaryFrame << " (bin " << leftBoundaryFrame/increment << ")" << endl; | 
| 2112 cerr << "Right: crop: " << rightCropFrame << " (bin " << rightCropFrame/increment << "); boundary: " << rightBoundaryFrame << " (bin " << rightBoundaryFrame/increment << ")" << endl; | 2094 cerr << "Right: crop: " << rightCropFrame << " (bin " << rightCropFrame/increment << "); boundary: " << rightBoundaryFrame << " (bin " << rightBoundaryFrame/increment << ")" << endl; | 
| 2114 | 2096 | 
| 2115 bufwid = int((rightBoundaryFrame - leftBoundaryFrame) / increment); | 2097 bufwid = int((rightBoundaryFrame - leftBoundaryFrame) / increment); | 
| 2116 | 2098 | 
| 2117 } else { | 2099 } else { | 
| 2118 | 2100 | 
| 2119 bufwid = w; | 2101 bufwid = repaintWidth; | 
| 2120 } | 2102 } | 
| 2121 | 2103 | 
| 2122 vector<int> binforx(bufwid); | 2104 vector<int> binforx(bufwid); | 
| 2123 vector<double> binfory(h); | 2105 vector<double> binfory(h); | 
| 2124 | 2106 | 
| 2151 m_drawBuffer.setColor((unsigned char)pixel, | 2133 m_drawBuffer.setColor((unsigned char)pixel, | 
| 2152 m_palette.getColour((unsigned char)pixel).rgb()); | 2134 m_palette.getColour((unsigned char)pixel).rgb()); | 
| 2153 } | 2135 } | 
| 2154 | 2136 | 
| 2155 m_drawBuffer.fill(0); | 2137 m_drawBuffer.fill(0); | 
| 2138 int attainedBufwid = bufwid; | |
| 2156 | 2139 | 
| 2157 if (m_binDisplay != PeakFrequencies) { | 2140 if (m_binDisplay != PeakFrequencies) { | 
| 2158 | 2141 | 
| 2159 for (int y = 0; y < h; ++y) { | 2142 for (int y = 0; y < h; ++y) { | 
| 2160 double q0 = 0, q1 = 0; | 2143 double q0 = 0, q1 = 0; | 
| 2163 } else { | 2146 } else { | 
| 2164 binfory[y] = q0; | 2147 binfory[y] = q0; | 
| 2165 } | 2148 } | 
| 2166 } | 2149 } | 
| 2167 | 2150 | 
| 2168 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache, | 2151 attainedBufwid = | 
| 2169 overallMag, overallMagChanged); | 2152 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache, | 
| 2153 overallMag, overallMagChanged); | |
| 2170 | 2154 | 
| 2171 } else { | 2155 } else { | 
| 2172 | 2156 | 
| 2173 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx, | 2157 attainedBufwid = | 
| 2174 minbin, maxbin, | 2158 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx, | 
| 2175 displayMinFreq, displayMaxFreq, | 2159 minbin, maxbin, | 
| 2176 logarithmic, | 2160 displayMinFreq, displayMaxFreq, | 
| 2177 overallMag, overallMagChanged); | 2161 logarithmic, | 
| 2178 } | 2162 overallMag, overallMagChanged); | 
| 2179 | 2163 } | 
| 2164 | |
| 2165 int failedToRepaint = bufwid - attainedBufwid; | |
| 2166 if (failedToRepaint < 0) { | |
| 2167 cerr << "WARNING: failedToRepaint < 0 (= " << failedToRepaint << ")" | |
| 2168 << endl; | |
| 2169 failedToRepaint = 0; | |
| 2170 } | |
| 2171 | |
| 2180 if (overallMagChanged) { | 2172 if (overallMagChanged) { | 
| 2181 m_viewMags[v] = overallMag; | 2173 m_viewMags[v] = overallMag; | 
| 2182 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2174 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2183 cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << endl; | 2175 cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << endl; | 
| 2184 #endif | 2176 #endif | 
| 2194 << ", height = " << h << endl; | 2186 << ", height = " << h << endl; | 
| 2195 #endif | 2187 #endif | 
| 2196 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied); | 2188 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied); | 
| 2197 } | 2189 } | 
| 2198 | 2190 | 
| 2199 if (w > 0) { | 2191 if (repaintWidth > 0) { | 
| 2200 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2192 | 
| 2201 cerr << "Painting " << w << "x" << h | 2193 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2194 cerr << "Painting " << repaintWidth << "x" << h | |
| 2202 << " from draw buffer at " << 0 << "," << 0 | 2195 << " from draw buffer at " << 0 << "," << 0 | 
| 2203 << " to " << w << "x" << h << " on cache at " | 2196 << " to " << repaintWidth << "x" << h << " on cache at " | 
| 2204 << x0 << "," << 0 << endl; | 2197 << x0 << "," << 0 << endl; | 
| 2205 #endif | 2198 #endif | 
| 2206 | 2199 | 
| 2207 QPainter cachePainter(&cache.image); | 2200 QPainter cachePainter(&cache.image); | 
| 2208 | 2201 | 
| 2232 (QRect(scaledLeftCrop, 0, | 2225 (QRect(scaledLeftCrop, 0, | 
| 2233 scaledRightCrop - scaledLeftCrop, h), | 2226 scaledRightCrop - scaledLeftCrop, h), | 
| 2234 scaled, | 2227 scaled, | 
| 2235 QRect(scaledLeftCrop - scaledLeft, 0, | 2228 QRect(scaledLeftCrop - scaledLeft, 0, | 
| 2236 scaledRightCrop - scaledLeftCrop, h)); | 2229 scaledRightCrop - scaledLeftCrop, h)); | 
| 2230 | |
| 2237 } else { | 2231 } else { | 
| 2238 cachePainter.drawImage(QRect(x0, 0, w, h), | 2232 | 
| 2233 cachePainter.drawImage(QRect(x0, 0, repaintWidth, h), | |
| 2239 m_drawBuffer, | 2234 m_drawBuffer, | 
| 2240 QRect(0, 0, w, h)); | 2235 QRect(0, 0, repaintWidth, h)); | 
| 2241 } | 2236 } | 
| 2242 | 2237 | 
| 2243 cachePainter.end(); | 2238 cachePainter.end(); | 
| 2239 } | |
| 2240 | |
| 2241 // update cache valid area based on painted area | |
| 2242 if (cache.validArea.width() > 0) { | |
| 2243 | |
| 2244 int left = std::min(cache.validArea.x(), x0); | |
| 2245 | |
| 2246 int wid = std::max(cache.validArea.x() + cache.validArea.width() - left, | |
| 2247 x1 - left); | |
| 2248 | |
| 2249 wid = wid - failedToRepaint; | |
| 2250 if (wid < 0) wid = 0; | |
| 2251 | |
| 2252 cache.validArea = QRect | |
| 2253 (left, cache.validArea.y(), wid, cache.validArea.height()); | |
| 2254 | |
| 2255 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
| 2256 cerr << "Valid area becomes " << cache.validArea.x() | |
| 2257 << ", " << cache.validArea.y() << ", " | |
| 2258 << cache.validArea.width() << "x" | |
| 2259 << cache.validArea.height() << endl; | |
| 2260 #endif | |
| 2261 | |
| 2262 } else { | |
| 2263 | |
| 2264 cache.validArea = QRect(x0, 0, x1 - x0, h); | |
| 2265 | |
| 2266 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
| 2267 cerr << "Valid area becomes " << x0 << ", 0, " << (x1-x0) | |
| 2268 << "x" << h << endl; | |
| 2269 #endif | |
| 2244 } | 2270 } | 
| 2245 | 2271 | 
| 2246 QRect pr = rect & cache.validArea; | 2272 QRect pr = rect & cache.validArea; | 
| 2247 | 2273 | 
| 2248 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2274 #ifdef DEBUG_SPECTROGRAM_REPAINT | 
| 2277 << ", " | 2303 << ", " | 
| 2278 << cache.image.width() - (cache.validArea.x() + | 2304 << cache.image.width() - (cache.validArea.x() + | 
| 2279 cache.validArea.width()) | 2305 cache.validArea.width()) | 
| 2280 << ")" << endl; | 2306 << ")" << endl; | 
| 2281 #endif | 2307 #endif | 
| 2282 v->getView()->update(cache.validArea.x() + cache.validArea.width(), | 2308 v->getView()->update | 
| 2283 0, | 2309 (cache.validArea.x() + cache.validArea.width(), | 
| 2284 cache.image.width() - (cache.validArea.x() + | 2310 0, | 
| 2285 cache.validArea.width()), | 2311 cache.image.width() - (cache.validArea.x() + | 
| 2286 h); | 2312 cache.validArea.width()), | 
| 2313 h); | |
| 2287 } | 2314 } | 
| 2288 } else { | 2315 } else { | 
| 2289 // overallMagChanged | 2316 // overallMagChanged | 
| 2290 cerr << "\noverallMagChanged - updating all\n" << endl; | 2317 cerr << "\noverallMagChanged - updating all\n" << endl; | 
| 2291 cache.validArea = QRect(); | 2318 cache.validArea = QRect(); | 
| 2305 m_lastPaintTime = std::chrono::duration<double>(diff).count(); | 2332 m_lastPaintTime = std::chrono::duration<double>(diff).count(); | 
| 2306 m_lastPaintBlockWidth = paintBlockWidth; | 2333 m_lastPaintBlockWidth = paintBlockWidth; | 
| 2307 } | 2334 } | 
| 2308 } | 2335 } | 
| 2309 | 2336 | 
| 2310 void | 2337 int | 
| 2311 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, | 2338 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, | 
| 2312 int w, | 2339 int w, | 
| 2313 int h, | 2340 int h, | 
| 2314 const vector<int> &binforx, | 2341 const vector<int> &binforx, | 
| 2315 int minbin, | 2342 int minbin, | 
| 2327 #endif | 2354 #endif | 
| 2328 if (minbin < 0) minbin = 0; | 2355 if (minbin < 0) minbin = 0; | 
| 2329 if (maxbin < 0) maxbin = minbin+1; | 2356 if (maxbin < 0) maxbin = minbin+1; | 
| 2330 | 2357 | 
| 2331 FFTModel *fft = getFFTModel(v); | 2358 FFTModel *fft = getFFTModel(v); | 
| 2332 if (!fft) return; | 2359 if (!fft) return 0; | 
| 2333 | 2360 | 
| 2334 FFTModel::PeakSet peakfreqs; | 2361 FFTModel::PeakSet peakfreqs; | 
| 2335 | 2362 | 
| 2336 int psx = -1; | 2363 int psx = -1; | 
| 2337 | 2364 | 
| 2420 if (overallMag.sample(mag)) overallMagChanged = true; | 2447 if (overallMag.sample(mag)) overallMagChanged = true; | 
| 2421 } | 2448 } | 
| 2422 } | 2449 } | 
| 2423 } | 2450 } | 
| 2424 } | 2451 } | 
| 2425 } | 2452 | 
| 2426 | 2453 return w; | 
| 2427 void | 2454 } | 
| 2455 | |
| 2456 int | |
| 2428 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v, | 2457 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v, | 
| 2429 int w, | 2458 int w, | 
| 2430 int h, | 2459 int h, | 
| 2431 const vector<int> &binforx, | 2460 const vector<int> &binforx, | 
| 2432 const vector<double> &binfory, | 2461 const vector<double> &binfory, | 
| 2458 maxbin = sourceModel->getHeight(); | 2487 maxbin = sourceModel->getHeight(); | 
| 2459 } else { | 2488 } else { | 
| 2460 sourceModel = fft = getFFTModel(v); | 2489 sourceModel = fft = getFFTModel(v); | 
| 2461 } | 2490 } | 
| 2462 | 2491 | 
| 2463 if (!sourceModel) return; | 2492 if (!sourceModel) return 0; | 
| 2464 | 2493 | 
| 2465 bool interpolate = false; | 2494 bool interpolate = false; | 
| 2466 Preferences::SpectrogramSmoothing smoothing = | 2495 Preferences::SpectrogramSmoothing smoothing = | 
| 2467 Preferences::getInstance()->getSpectrogramSmoothing(); | 2496 Preferences::getInstance()->getSpectrogramSmoothing(); | 
| 2468 if (smoothing == Preferences::SpectrogramInterpolated || | 2497 if (smoothing == Preferences::SpectrogramInterpolated || | 
| 2654 unsigned char peakpix = getDisplayValue(v, peak); | 2683 unsigned char peakpix = getDisplayValue(v, peak); | 
| 2655 | 2684 | 
| 2656 m_drawBuffer.setPixel(x, h-y-1, peakpix); | 2685 m_drawBuffer.setPixel(x, h-y-1, peakpix); | 
| 2657 } | 2686 } | 
| 2658 } | 2687 } | 
| 2688 | |
| 2689 return w; | |
| 2659 } | 2690 } | 
| 2660 | 2691 | 
| 2661 void | 2692 void | 
| 2662 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const | 2693 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const | 
| 2663 { | 2694 { | 
