comparison layer/SpectrogramLayer.cpp @ 480:567b94e627b8

* start introducing another rendering method
author Chris Cannam
date Tue, 03 Feb 2009 15:21:28 +0000
parents 0033dbfb92e3
children 74a7729e3653
comparison
equal deleted inserted replaced
479:0033dbfb92e3 480:567b94e627b8
37 #include <QMouseEvent> 37 #include <QMouseEvent>
38 #include <QTextStream> 38 #include <QTextStream>
39 39
40 #include <iostream> 40 #include <iostream>
41 41
42 using std::cerr;
43 using std::endl;
42 #include <cassert> 44 #include <cassert>
43 #include <cmath> 45 #include <cmath>
44 46
45 #define DEBUG_SPECTROGRAM_REPAINT 1 47 #define DEBUG_SPECTROGRAM_REPAINT 1
46 48
2071 << "x" << h << std::endl; 2073 << "x" << h << std::endl;
2072 #endif 2074 #endif
2073 cache.validArea = QRect(x0, 0, x1 - x0, h); 2075 cache.validArea = QRect(x0, 0, x1 - x0, h);
2074 } 2076 }
2075 2077
2078 if (xPixelRatio != 1.f) {
2079 x0 = int((int(x0 / xPixelRatio) - 4) * xPixelRatio + 0.0001);
2080 x1 = int((int(x1 / xPixelRatio) + 4) * xPixelRatio + 0.0001);
2081 }
2082
2076 int w = x1 - x0; 2083 int w = x1 - x0;
2077 2084
2078 #ifdef DEBUG_SPECTROGRAM_REPAINT 2085 #ifdef DEBUG_SPECTROGRAM_REPAINT
2079 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl; 2086 std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl;
2080 #endif 2087 #endif
2167 size_t pixels = 0; 2174 size_t pixels = 0;
2168 #endif 2175 #endif
2169 2176
2170 Profiler outerprof("SpectrogramLayer::paint: all cols"); 2177 Profiler outerprof("SpectrogramLayer::paint: all cols");
2171 2178
2179 int bufwid = w / xPixelRatio;
2180 int binforx[bufwid + 1];
2181 int binfory[h + 1];
2182
2183 for (int x = 0; x <= bufwid; ++x) {
2184 int vx = int(x0 + x * xPixelRatio + 0.0001);
2185 float s0 = 0, s1 = 0;
2186 if (!getXBinRange(v, vx, s0, s1)) {
2187 binforx[x] = -1;
2188 } else {
2189 binforx[x] = int(s0 + 0.0001);
2190 }
2191 }
2192
2193 for (int y = 0; y < h; ++y) {
2194 float q0 = 0, q1 = 0;
2195 if (!getYBinRange(v, h-y, q0, q1)) {
2196 binfory[y] = -1;
2197 } else {
2198 binfory[y] = int(q0 + 0.0001);
2199 }
2200 }
2201 binfory[h] = binfory[h-1];
2202
2203 paintColumnValues2(v, fft, bufwid, h, binforx, binfory);
2204
2205 /*
2172 for (int x = 0; x < w / xPixelRatio; ++x) { 2206 for (int x = 0; x < w / xPixelRatio; ++x) {
2173 2207
2174 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column"); 2208 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column");
2175 2209
2176 runOutOfData = !paintColumnValues(v, fft, x0, x, 2210 runOutOfData = !paintColumnValues(v, fft, x0, x,
2184 std::cerr << "Run out of data -- dropping out of loop" << std::endl; 2218 std::cerr << "Run out of data -- dropping out of loop" << std::endl;
2185 #endif 2219 #endif
2186 break; 2220 break;
2187 } 2221 }
2188 } 2222 }
2189 2223 */
2190 #ifdef DEBUG_SPECTROGRAM_REPAINT 2224 #ifdef DEBUG_SPECTROGRAM_REPAINT
2191 std::cerr << pixels << " pixels drawn" << std::endl; 2225 // std::cerr << pixels << " pixels drawn" << std::endl;
2192 #endif 2226 #endif
2193 2227
2194 if (overallMagChanged) { 2228 if (overallMagChanged) {
2195 m_viewMags[v] = overallMag; 2229 m_viewMags[v] = overallMag;
2196 #ifdef DEBUG_SPECTROGRAM_REPAINT 2230 #ifdef DEBUG_SPECTROGRAM_REPAINT
2214 cache.image = QImage(v->width(), h, QImage::Format_RGB32); 2248 cache.image = QImage(v->width(), h, QImage::Format_RGB32);
2215 } 2249 }
2216 2250
2217 if (w > 0) { 2251 if (w > 0) {
2218 #ifdef DEBUG_SPECTROGRAM_REPAINT 2252 #ifdef DEBUG_SPECTROGRAM_REPAINT
2219 std::cerr << "Painting " << w << "x" << h 2253 std::cerr << "Painting " << w/xPixelRatio << "x" << h
2220 << " from draw buffer at " << 0 << "," << 0 2254 << " from draw buffer at " << 0 << "," << 0
2221 << " to cache at " << x0 << "," << 0 << std::endl; 2255 << " to " << w << "x" << h << " on cache at "
2256 << x0 << "," << 0 << std::endl;
2222 #endif 2257 #endif
2223 2258
2224 QPainter cachePainter(&cache.image); 2259 QPainter cachePainter(&cache.image);
2225 cachePainter.setRenderHint(QPainter::SmoothPixmapTransform, true); 2260 cachePainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
2226 cachePainter.drawImage(QRect(x0, 0, w, h), 2261 cachePainter.drawImage(QRect(x0, 0, w, h),
2295 } 2330 }
2296 2331
2297 //!!! if (fftSuspended) fft->resume(); 2332 //!!! if (fftSuspended) fft->resume();
2298 } 2333 }
2299 2334
2335 bool
2336 SpectrogramLayer::paintColumnValues2(View *v,
2337 FFTModel *fft,
2338 int w,
2339 int h,
2340 int *binforx, // w+1 values
2341 int *binfory // h+1 values
2342 ) const
2343 {
2344 // paint onto m_drawBuffer
2345
2346 int minbin = binfory[0];
2347 int maxbin = binfory[h-1];
2348
2349 cerr << "minbin " << minbin << ", maxbin " << maxbin << endl;
2350 if (minbin < 0) minbin = 0;
2351 if (maxbin < 0) maxbin = minbin+1;
2352
2353 int psx = -1;
2354 float values[maxbin - minbin + 1];
2355
2356 for (int x = 0; x < w; ++x) {
2357
2358 for (int y = 0; y < h; ++y) {
2359
2360 unsigned char peakpix = 0;
2361
2362 int sx0 = binforx[x];
2363 int sx1 = binforx[x+1];
2364 if (sx0 < 0) sx0 = sx1 - 1;
2365 if (sx0 < 0) continue;
2366 if (sx1 <= sx0) sx1 = sx0 + 1;
2367
2368 for (int sx = sx0; sx < sx1; ++sx) {
2369
2370 if (sx < 0 || sx >= int(fft->getWidth())) continue;
2371
2372 if (!m_synchronous) {
2373 if (!fft->isColumnAvailable(sx)) {
2374 #ifdef DEBUG_SPECTROGRAM_REPAINT
2375 std::cerr << "Met unavailable column at col " << sx << std::endl;
2376 #endif
2377 return false;
2378 }
2379 }
2380
2381 if (sx != psx) {
2382 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2383 psx = sx;
2384 }
2385
2386 int sy0 = binfory[y];
2387 int sy1 = binfory[y+1];
2388 if (sy0 < 0) sy0 = sy1 - 1;
2389 if (sy0 < 0) continue;
2390 if (sy1 <= sy0) sy1 = sy0 + 1;
2391
2392 // cerr << "sy0 " << sy0 << " sy1 " << sy1 << endl;
2393
2394 //!!! review
2395 for (int sy = sy0; sy < sy1; ++sy) {
2396
2397 float value = values[sy - minbin];
2398
2399 if (m_colourScale != PhaseColourScale) {
2400 if (!m_normalizeColumns) {
2401 value /= (m_fftSize/2.f);
2402 }
2403 //!!! mag.sample(value);
2404 value *= m_gain;
2405 }
2406
2407 unsigned char pix = getDisplayValue(v, value);
2408 if (pix > peakpix) peakpix = pix;
2409 // cerr <<x<<","<<y<<" -> "<<sx<<","<<sy<<" -> "<<values[sy]<<" -> "<<(int)pix<< endl;
2410 }
2411 }
2412
2413 m_drawBuffer.setPixel(x, h-y-1, peakpix);
2414 }
2415 }
2416
2417 return true;
2418 }
2300 2419
2301 bool 2420 bool
2302 SpectrogramLayer::paintColumnValues(View *v, 2421 SpectrogramLayer::paintColumnValues(View *v,
2303 FFTModel *fft, 2422 FFTModel *fft,
2304 int x0, 2423 int x0,
2335 2454
2336 float s0 = 0, s1 = 0; 2455 float s0 = 0, s1 = 0;
2337 2456
2338 if (!getXBinRange(v, x0 + x * xPixelRatio, s0, s1)) { 2457 if (!getXBinRange(v, x0 + x * xPixelRatio, s0, s1)) {
2339 #ifdef DEBUG_SPECTROGRAM_REPAINT 2458 #ifdef DEBUG_SPECTROGRAM_REPAINT
2340 std::cerr << "Out of range at " << x0 + x << std::endl; 2459 // std::cerr << "Out of range at " << x0 + x << std::endl;
2341 #endif 2460 #endif
2342 assert(x <= m_drawBuffer.width()); 2461 assert(x <= m_drawBuffer.width());
2343 return true; 2462 return true;
2344 } 2463 }
2345 2464