Mercurial > hg > svgui
comparison layer/Colour3DPlotRenderer.cpp @ 1212:a1ee3108d1d3 3.0-integration
Make the colour 3d plot renderer able to support more than one level of peak cache; introduce a second "peak" cache for the spectrogram layer that actually has a 1-1 column relationship with the underlying FFT model, and use it in addition to the existing peak cache if memory is plentiful. Makes spectrograms appear much faster in many common situations.
author | Chris Cannam |
---|---|
date | Thu, 05 Jan 2017 14:02:54 +0000 |
parents | 84042e8c3c03 |
children | 34df6ff25472 |
comparison
equal
deleted
inserted
replaced
1211:7a19738b9762 | 1212:a1ee3108d1d3 |
---|---|
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 ColumnOp::Column | 288 ColumnOp::Column |
289 Colour3DPlotRenderer::getColumn(int sx, int minbin, int nbins, | 289 Colour3DPlotRenderer::getColumn(int sx, int minbin, int nbins, |
290 bool usePeakCache) const | 290 int peakCacheIndex) const |
291 { | 291 { |
292 Profiler profiler("Colour3DPlotRenderer::getColumn"); | 292 Profiler profiler("Colour3DPlotRenderer::getColumn"); |
293 | 293 |
294 // order: | 294 // order: |
295 // get column -> scale -> normalise -> record extents -> | 295 // get column -> scale -> normalise -> record extents -> |
307 | 307 |
308 column = vector<float>(fullColumn.data() + minbin, | 308 column = vector<float>(fullColumn.data() + minbin, |
309 fullColumn.data() + minbin + nbins); | 309 fullColumn.data() + minbin + nbins); |
310 | 310 |
311 } else { | 311 } else { |
312 | 312 |
313 ColumnOp::Column fullColumn = | 313 ColumnOp::Column fullColumn = |
314 (usePeakCache ? m_sources.peakCache : m_sources.source)-> | 314 (peakCacheIndex >= 0 ? |
315 getColumn(sx); | 315 m_sources.peakCaches[peakCacheIndex] : |
316 m_sources.source) | |
317 ->getColumn(sx); | |
316 | 318 |
317 column = vector<float>(fullColumn.data() + minbin, | 319 column = vector<float>(fullColumn.data() + minbin, |
318 fullColumn.data() + minbin + nbins); | 320 fullColumn.data() + minbin + nbins); |
319 | 321 |
320 column = ColumnOp::applyGain(column, m_params.scaleFactor); | 322 column = ColumnOp::applyGain(column, m_params.scaleFactor); |
506 clearDrawBuffer(repaintWidth, h); | 508 clearDrawBuffer(repaintWidth, h); |
507 | 509 |
508 vector<int> binforx(repaintWidth); | 510 vector<int> binforx(repaintWidth); |
509 vector<double> binfory(h); | 511 vector<double> binfory(h); |
510 | 512 |
511 bool usePeakCache = false; | |
512 int binsPerPeak = 1; | |
513 int zoomLevel = v->getZoomLevel(); | 513 int zoomLevel = v->getZoomLevel(); |
514 int binResolution = model->getResolution(); | 514 int binResolution = model->getResolution(); |
515 | 515 |
516 for (int x = 0; x < repaintWidth; ++x) { | 516 for (int x = 0; x < repaintWidth; ++x) { |
517 sv_frame_t f0 = v->getFrameForX(x0 + x); | 517 sv_frame_t f0 = v->getFrameForX(x0 + x); |
518 double s0 = double(f0 - model->getStartFrame()) / binResolution; | 518 double s0 = double(f0 - model->getStartFrame()) / binResolution; |
519 binforx[x] = int(s0 + 0.0001); | 519 binforx[x] = int(s0 + 0.0001); |
520 } | 520 } |
521 | 521 |
522 if (m_sources.peakCache) { | 522 int peakCacheIndex = -1; |
523 binsPerPeak = m_sources.peakCache->getColumnsPerPeak(); | 523 int binsPerPeak = -1; |
524 usePeakCache = (zoomLevel >= binResolution * binsPerPeak); | 524 |
525 if (m_params.colourScale.getScale() == | 525 if (m_params.colourScale.getScale() != ColourScaleType::Phase) { |
526 ColourScaleType::Phase) { | 526 for (int ix = 0; in_range_for(m_sources.peakCaches, ix); ++ix) { |
527 usePeakCache = false; | 527 int bpp = m_sources.peakCaches[ix]->getColumnsPerPeak(); |
528 int equivZoom = binResolution * bpp; | |
529 if (zoomLevel >= equivZoom) { | |
530 // this peak cache would work, though it might not be best | |
531 if (bpp > binsPerPeak) { | |
532 // ok, it's better than the best one we've found so far | |
533 peakCacheIndex = ix; | |
534 binsPerPeak = bpp; | |
535 } | |
536 } | |
528 } | 537 } |
529 } | 538 } |
530 | 539 |
531 SVDEBUG << "[PIX] zoomLevel = " << zoomLevel | 540 SVDEBUG << "[PIX] zoomLevel = " << zoomLevel |
532 << ", binResolution " << binResolution | 541 << ", binResolution " << binResolution |
533 << ", binsPerPeak " << binsPerPeak | 542 << ", binsPerPeak " << binsPerPeak |
534 << ", peak cache " << m_sources.peakCache | 543 << ", peakCacheIndex " << peakCacheIndex |
535 << ", usePeakCache = " << usePeakCache | 544 << ", peakCaches " << m_sources.peakCaches.size() |
536 << endl; | 545 << endl; |
537 | 546 |
538 for (int y = 0; y < h; ++y) { | 547 for (int y = 0; y < h; ++y) { |
539 binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1); | 548 binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1); |
540 } | 549 } |
553 } else { | 562 } else { |
554 attainedWidth = renderDrawBuffer(repaintWidth, | 563 attainedWidth = renderDrawBuffer(repaintWidth, |
555 h, | 564 h, |
556 binforx, | 565 binforx, |
557 binfory, | 566 binfory, |
558 usePeakCache, | 567 peakCacheIndex, |
559 rightToLeft, | 568 rightToLeft, |
560 timeConstrained); | 569 timeConstrained); |
561 } | 570 } |
562 | 571 |
563 if (attainedWidth == 0) return; | 572 if (attainedWidth == 0) return; |
718 | 727 |
719 int attainedWidth = renderDrawBuffer(drawBufferWidth, | 728 int attainedWidth = renderDrawBuffer(drawBufferWidth, |
720 h, | 729 h, |
721 binforx, | 730 binforx, |
722 binfory, | 731 binfory, |
723 false, | 732 -1, |
724 false, | 733 false, |
725 false); | 734 false); |
726 | 735 |
727 if (attainedWidth == 0) return; | 736 if (attainedWidth == 0) return; |
728 | 737 |
729 int scaledLeft = v->getXForFrame(leftBoundaryFrame); | 738 int scaledLeft = v->getXForFrame(leftBoundaryFrame); |
730 int scaledRight = v->getXForFrame(rightBoundaryFrame); | 739 int scaledRight = v->getXForFrame(rightBoundaryFrame); |
731 | 740 |
732 #ifdef DEBUG_COLOUR_PLOT_REPAINT | 741 #ifdef DEBUG_COLOUR_PLOT_REPAINT |
733 cerr << "scaling draw buffer from width " << m_drawBuffer.width() | 742 SVDEBUG << "scaling draw buffer from width " << m_drawBuffer.width() |
734 << " to " << (scaledRight - scaledLeft) << " (nb drawBufferWidth = " | 743 << " to " << (scaledRight - scaledLeft) << " (nb drawBufferWidth = " |
735 << drawBufferWidth << ")" << endl; | 744 << drawBufferWidth << ")" << endl; |
736 #endif | 745 #endif |
737 | 746 |
738 QImage scaled = scaleDrawBufferImage | 747 QImage scaled = scaleDrawBufferImage |
739 (m_drawBuffer, scaledRight - scaledLeft, h); | 748 (m_drawBuffer, scaledRight - scaledLeft, h); |
740 | 749 |
781 | 790 |
782 int | 791 int |
783 Colour3DPlotRenderer::renderDrawBuffer(int w, int h, | 792 Colour3DPlotRenderer::renderDrawBuffer(int w, int h, |
784 const vector<int> &binforx, | 793 const vector<int> &binforx, |
785 const vector<double> &binfory, | 794 const vector<double> &binfory, |
786 bool usePeakCache, | 795 int peakCacheIndex, |
787 bool rightToLeft, | 796 bool rightToLeft, |
788 bool timeConstrained) | 797 bool timeConstrained) |
789 { | 798 { |
790 // Callers must have checked that the appropriate subset of | 799 // Callers must have checked that the appropriate subset of |
791 // Sources data members are set for the supplied flags (e.g. that | 800 // Sources data members are set for the supplied flags (e.g. that |
792 // peakCache model exists if usePeakCache) | 801 // peakCache corresponding to peakCacheIndex exists) |
793 | 802 |
794 RenderTimer timer(timeConstrained ? | 803 RenderTimer timer(timeConstrained ? |
795 RenderTimer::FastRender : | 804 RenderTimer::FastRender : |
796 RenderTimer::NoTimeout); | 805 RenderTimer::NoTimeout); |
797 | 806 |
798 Profiler profiler("Colour3DPlotRenderer::renderDrawBuffer"); | 807 Profiler profiler("Colour3DPlotRenderer::renderDrawBuffer"); |
799 | 808 |
800 int divisor = 1; | 809 int divisor = 1; |
801 const DenseThreeDimensionalModel *sourceModel = m_sources.source; | 810 const DenseThreeDimensionalModel *sourceModel = m_sources.source; |
802 if (usePeakCache) { | 811 if (peakCacheIndex >= 0) { |
803 divisor = m_sources.peakCache->getColumnsPerPeak(); | 812 divisor = m_sources.peakCaches[peakCacheIndex]->getColumnsPerPeak(); |
804 sourceModel = m_sources.peakCache; | 813 sourceModel = m_sources.peakCaches[peakCacheIndex]; |
805 } | 814 } |
806 | 815 |
807 SVDEBUG << "renderDrawBuffer: w = " << w << ", h = " << h | 816 SVDEBUG << "renderDrawBuffer: w = " << w << ", h = " << h |
808 << ", usePeakCache = " << usePeakCache << " (divisor = " | 817 << ", peakCacheIndex = " << peakCacheIndex << " (divisor = " |
809 << divisor << "), rightToLeft = " << rightToLeft | 818 << divisor << "), rightToLeft = " << rightToLeft |
810 << ", timeConstrained = " << timeConstrained << endl; | 819 << ", timeConstrained = " << timeConstrained << endl; |
811 SVDEBUG << "renderDrawBuffer: normalization = " << int(m_params.normalization) | 820 SVDEBUG << "renderDrawBuffer: normalization = " << int(m_params.normalization) |
812 << ", binDisplay = " << int(m_params.binDisplay) | 821 << ", binDisplay = " << int(m_params.binDisplay) |
813 << ", binScale = " << int(m_params.binScale) | 822 << ", binScale = " << int(m_params.binScale) |
885 // get column -> scale -> normalise -> record extents -> | 894 // get column -> scale -> normalise -> record extents -> |
886 // peak pick -> distribute/interpolate -> apply display gain | 895 // peak pick -> distribute/interpolate -> apply display gain |
887 | 896 |
888 // this does the first three: | 897 // this does the first three: |
889 ColumnOp::Column column = getColumn(sx, minbin, nbins, | 898 ColumnOp::Column column = getColumn(sx, minbin, nbins, |
890 usePeakCache); | 899 peakCacheIndex); |
891 | 900 |
892 magRange.sample(column); | 901 magRange.sample(column); |
893 | 902 |
894 if (m_params.binDisplay == BinDisplay::PeakBins) { | 903 if (m_params.binDisplay == BinDisplay::PeakBins) { |
895 column = ColumnOp::peakPick(column); | 904 column = ColumnOp::peakPick(column); |
936 m_magRanges.push_back(magRange); | 945 m_magRanges.push_back(magRange); |
937 } | 946 } |
938 | 947 |
939 double fractionComplete = double(columnCount) / double(w); | 948 double fractionComplete = double(columnCount) / double(w); |
940 if (timer.outOfTime(fractionComplete)) { | 949 if (timer.outOfTime(fractionComplete)) { |
941 cerr << "out of time" << endl; | 950 SVDEBUG << "out of time" << endl; |
942 return columnCount; | 951 return columnCount; |
943 } | 952 } |
944 } | 953 } |
945 | 954 |
946 return columnCount; | 955 return columnCount; |