Mercurial > hg > svgui
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 } |