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;