comparison layer/SpectrogramLayer.cpp @ 484:a926fca1f280

* Make use of peak cache in spectrogram
author Chris Cannam
date Wed, 04 Feb 2009 15:03:42 +0000
parents 18f38f564d7c
children 3f9fddc890e0
comparison
equal deleted inserted replaced
483:18f38f564d7c 484:a926fca1f280
2 2
3 /* 3 /*
4 Sonic Visualiser 4 Sonic Visualiser
5 An audio file viewer and annotation editor. 5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London. 6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam and QMUL. 7 This file copyright 2006-2009 Chris Cannam and QMUL.
8 8
9 This program is free software; you can redistribute it and/or 9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as 10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the 11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file 12 License, or (at your option) any later version. See the file
24 #include "base/RangeMapper.h" 24 #include "base/RangeMapper.h"
25 #include "base/LogRange.h" 25 #include "base/LogRange.h"
26 #include "widgets/CommandHistory.h" 26 #include "widgets/CommandHistory.h"
27 #include "ColourMapper.h" 27 #include "ColourMapper.h"
28 #include "ImageRegionFinder.h" 28 #include "ImageRegionFinder.h"
29 #include "data/model/Dense3DModelPeakCache.h"
29 30
30 #include <QPainter> 31 #include <QPainter>
31 #include <QImage> 32 #include <QImage>
32 #include <QPixmap> 33 #include <QPixmap>
33 #include <QRect> 34 #include <QRect>
993 if (!replaced) emit sliceableModelReplaced(m_sliceableModel, 0); 994 if (!replaced) emit sliceableModelReplaced(m_sliceableModel, 0);
994 } 995 }
995 996
996 delete m_fftModels[v].first; 997 delete m_fftModels[v].first;
997 m_fftModels.erase(v); 998 m_fftModels.erase(v);
999
1000 delete m_peakCaches[v];
1001 m_peakCaches.erase(v);
998 } 1002 }
999 1003
1000 } else { 1004 } else {
1001 1005
1002 Layer::setLayerDormant(v, false); 1006 Layer::setLayerDormant(v, false);
1606 #ifdef DEBUG_SPECTROGRAM_REPAINT 1610 #ifdef DEBUG_SPECTROGRAM_REPAINT
1607 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a model with the wrong height (" << m_fftModels[v].first->getHeight() << ", wanted " << (fftSize / 2 + 1) << ")" << std::endl; 1611 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a model with the wrong height (" << m_fftModels[v].first->getHeight() << ", wanted " << (fftSize / 2 + 1) << ")" << std::endl;
1608 #endif 1612 #endif
1609 delete m_fftModels[v].first; 1613 delete m_fftModels[v].first;
1610 m_fftModels.erase(v); 1614 m_fftModels.erase(v);
1615 delete m_peakCaches[v];
1616 m_peakCaches.erase(v);
1611 } else { 1617 } else {
1612 #ifdef DEBUG_SPECTROGRAM_REPAINT 1618 #ifdef DEBUG_SPECTROGRAM_REPAINT
1613 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[v].first->getHeight() << std::endl; 1619 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[v].first->getHeight() << std::endl;
1614 #endif 1620 #endif
1615 return m_fftModels[v].first; 1621 return m_fftModels[v].first;
1658 } 1664 }
1659 1665
1660 return m_fftModels[v].first; 1666 return m_fftModels[v].first;
1661 } 1667 }
1662 1668
1669 Dense3DModelPeakCache *
1670 SpectrogramLayer::getPeakCache(const View *v) const
1671 {
1672 if (!m_peakCaches[v]) {
1673 FFTModel *f = getFFTModel(v);
1674 if (!f) return 0;
1675 m_peakCaches[v] = new Dense3DModelPeakCache(f, 8);
1676 }
1677 return m_peakCaches[v];
1678 }
1679
1663 const Model * 1680 const Model *
1664 SpectrogramLayer::getSliceableModel() const 1681 SpectrogramLayer::getSliceableModel() const
1665 { 1682 {
1666 if (m_sliceableModel) return m_sliceableModel; 1683 if (m_sliceableModel) return m_sliceableModel;
1667 if (m_fftModels.empty()) return 0; 1684 if (m_fftModels.empty()) return 0;
1776 // in the cache-fill thread above. 1793 // in the cache-fill thread above.
1777 //!!! no longer use cache-fill thread 1794 //!!! no longer use cache-fill thread
1778 const_cast<SpectrogramLayer *>(this)->Layer::setLayerDormant(v, false); 1795 const_cast<SpectrogramLayer *>(this)->Layer::setLayerDormant(v, false);
1779 1796
1780 size_t fftSize = getFFTSize(v); 1797 size_t fftSize = getFFTSize(v);
1798 /*
1781 FFTModel *fft = getFFTModel(v); 1799 FFTModel *fft = getFFTModel(v);
1782 if (!fft) { 1800 if (!fft) {
1783 std::cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << std::endl; 1801 std::cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << std::endl;
1784 return; 1802 return;
1785 } 1803 }
1786 1804 */
1787 ImageCache &cache = m_imageCaches[v]; 1805 ImageCache &cache = m_imageCaches[v];
1788 1806
1789 #ifdef DEBUG_SPECTROGRAM_REPAINT 1807 #ifdef DEBUG_SPECTROGRAM_REPAINT
1790 std::cerr << "SpectrogramLayer::paint(): image cache valid area " << cache. 1808 std::cerr << "SpectrogramLayer::paint(): image cache valid area " << cache.
1791 1809
2209 } 2227 }
2210 2228
2211 int binforx[bufwid]; 2229 int binforx[bufwid];
2212 int binfory[h]; 2230 int binfory[h];
2213 2231
2232 bool usePeaksCache = false;
2233
2214 if (bufferBinResolution) { 2234 if (bufferBinResolution) {
2215 for (int x = 0; x < bufwid; ++x) { 2235 for (int x = 0; x < bufwid; ++x) {
2216 binforx[x] = (leftBoundaryFrame / increment) + x; 2236 binforx[x] = (leftBoundaryFrame / increment) + x;
2217 // cerr << "binforx[" << x << "] = " << binforx[x] << endl; 2237 // cerr << "binforx[" << x << "] = " << binforx[x] << endl;
2218 } 2238 }
2227 } 2247 }
2228 } 2248 }
2229 if (m_drawBuffer.width() < bufwid || m_drawBuffer.height() < h) { 2249 if (m_drawBuffer.width() < bufwid || m_drawBuffer.height() < h) {
2230 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); 2250 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8);
2231 } 2251 }
2252 usePeaksCache = (increment * 8) < zoomLevel;
2232 } 2253 }
2233 2254
2234 m_drawBuffer.setNumColors(256); 2255 m_drawBuffer.setNumColors(256);
2235 for (int pixel = 0; pixel < 256; ++pixel) { 2256 for (int pixel = 0; pixel < 256; ++pixel) {
2236 m_drawBuffer.setColor(pixel, m_palette.getColour(pixel).rgb()); 2257 m_drawBuffer.setColor(pixel, m_palette.getColour(pixel).rgb());
2245 } else { 2266 } else {
2246 binfory[y] = int(q0 + 0.0001); 2267 binfory[y] = int(q0 + 0.0001);
2247 } 2268 }
2248 } 2269 }
2249 2270
2250 paintDrawBuffer(v, fft, bufwid, h, binforx, binfory); 2271 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache);
2251 2272
2252 /* 2273 /*
2253 for (int x = 0; x < w / xPixelRatio; ++x) { 2274 for (int x = 0; x < w / xPixelRatio; ++x) {
2254 2275
2255 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column"); 2276 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column");
2402 //!!! if (fftSuspended) fft->resume(); 2423 //!!! if (fftSuspended) fft->resume();
2403 } 2424 }
2404 2425
2405 bool 2426 bool
2406 SpectrogramLayer::paintDrawBuffer(View *v, 2427 SpectrogramLayer::paintDrawBuffer(View *v,
2407 FFTModel *fft,
2408 int w, 2428 int w,
2409 int h, 2429 int h,
2410 int *binforx, 2430 int *binforx,
2411 int *binfory) const 2431 int *binfory,
2432 bool usePeaksCache) const
2412 { 2433 {
2413 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); 2434 Profiler profiler("SpectrogramLayer::paintDrawBuffer");
2414 2435
2415 int minbin = binfory[0]; 2436 int minbin = binfory[0];
2416 int maxbin = binfory[h-1]; 2437 int maxbin = binfory[h-1];
2417 2438
2418 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; 2439 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl;
2419 if (minbin < 0) minbin = 0; 2440 if (minbin < 0) minbin = 0;
2420 if (maxbin < 0) maxbin = minbin+1; 2441 if (maxbin < 0) maxbin = minbin+1;
2421 2442
2443 DenseThreeDimensionalModel *sourceModel = 0;
2444 FFTModel *fft = 0;
2445 int divisor = 1;
2446 cerr << "Note: bin display = " << m_binDisplay << ", w = " << w << ", binforx[" << w-1 << "] = " << binforx[w-1] << ", binforx[0] = " << binforx[0] << endl;
2447 if (usePeaksCache) { //!!!
2448 sourceModel = getPeakCache(v);
2449 divisor = 8;//!!!
2450 minbin = 0;
2451 maxbin = sourceModel->getHeight();
2452 } else {
2453 sourceModel = fft = getFFTModel(v);
2454 }
2455
2456 if (!sourceModel) return false;
2457
2422 int psx = -1; 2458 int psx = -1;
2423 float values[maxbin - minbin + 1]; 2459 float values[maxbin - minbin + 1];
2460 DenseThreeDimensionalModel::Column c;
2424 float peaks[h]; 2461 float peaks[h];
2425 2462
2426 for (int x = 0; x < w; ++x) { 2463 for (int x = 0; x < w; ++x) {
2427 2464
2428 if (binforx[x] < 0) continue; 2465 if (binforx[x] < 0) continue;
2429 2466
2430 int sx0 = binforx[x]; 2467 int sx0 = binforx[x] / divisor;
2431 int sx1 = sx0; 2468 int sx1 = sx0;
2432 if (x+1 < w) sx1 = binforx[x+1]; 2469 if (x+1 < w) sx1 = binforx[x+1] / divisor;
2433 if (sx0 < 0) sx0 = sx1 - 1; 2470 if (sx0 < 0) sx0 = sx1 - 1;
2434 if (sx0 < 0) continue; 2471 if (sx0 < 0) continue;
2435 if (sx1 <= sx0) sx1 = sx0 + 1; 2472 if (sx1 <= sx0) sx1 = sx0 + 1;
2436 2473
2437 for (int y = 0; y < h; ++y) peaks[y] = 0.f; 2474 for (int y = 0; y < h; ++y) peaks[y] = 0.f;
2438 2475
2439 for (int sx = sx0; sx < sx1; ++sx) { 2476 for (int sx = sx0; sx < sx1; ++sx) {
2440 2477
2441 if (sx < 0 || sx >= int(fft->getWidth())) continue; 2478 if (sx < 0 || sx >= int(sourceModel->getWidth())) continue;
2442 2479
2443 if (!m_synchronous) { 2480 if (!m_synchronous) {
2444 if (!fft->isColumnAvailable(sx)) { 2481 if (!sourceModel->isColumnAvailable(sx)) {
2445 #ifdef DEBUG_SPECTROGRAM_REPAINT 2482 #ifdef DEBUG_SPECTROGRAM_REPAINT
2446 std::cerr << "Met unavailable column at col " << sx << std::endl; 2483 std::cerr << "Met unavailable column at col " << sx << std::endl;
2447 #endif 2484 #endif
2448 return false; 2485 return false;
2449 } 2486 }
2450 } 2487 }
2451 2488
2452 if (sx != psx) { 2489 if (sx != psx) {
2453 cerr << "Retrieving column " << sx << endl; 2490 if (fft) {
2454 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2491 cerr << "Retrieving column " << sx << " from fft directly" << endl;
2492 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2493 } else {
2494 cerr << "Retrieving column " << sx << " from peaks cache" << endl;
2495 c = sourceModel->getColumn(sx);
2496 }
2455 psx = sx; 2497 psx = sx;
2456 } 2498 }
2457 2499
2458 for (int y = 0; y < h; ++y) { 2500 for (int y = 0; y < h; ++y) {
2459 2501
2470 //!!! magnitudes here, we can just use peak of the 2512 //!!! magnitudes here, we can just use peak of the
2471 //!!! float values 2513 //!!! float values
2472 2514
2473 for (int sy = sy0; sy < sy1; ++sy) { 2515 for (int sy = sy0; sy < sy1; ++sy) {
2474 2516
2475 float value = values[sy - minbin]; 2517 float value = 0.f;
2518 if (fft) value = values[sy - minbin];
2519 else value = c[sy];
2520
2476 /* 2521 /*
2477 if (m_colourScale != PhaseColourScale) { 2522 if (m_colourScale != PhaseColourScale) {
2478 if (!m_normalizeColumns) { 2523 if (!m_normalizeColumns) {
2479 value /= (m_fftSize/2.f); 2524 value /= (m_fftSize/2.f);
2480 } 2525 }