comparison layer/Colour3DPlotRenderer.cpp @ 1097:92ac1fce7102 spectrogram-minor-refactor

Introduce peak frequency rendering (basics of)
author Chris Cannam
date Mon, 11 Jul 2016 16:03:39 +0100
parents 6288f1b5f49b
children 5c6271734790
comparison
equal deleted inserted replaced
1096:6288f1b5f49b 1097:92ac1fce7102
277 277
278 for (int y = 0; y < h; ++y) { 278 for (int y = 0; y < h; ++y) {
279 binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1); 279 binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1);
280 } 280 }
281 281
282 int attainedWidth = renderDrawBuffer(repaintWidth, 282 int attainedWidth;
283
284 if (m_params.binDisplay == PeakFrequencies) {
285 attainedWidth = renderDrawBufferPeakFrequencies(v,
286 repaintWidth,
287 h,
288 binforx,
289 binfory,
290 rightToLeft,
291 timeConstrained);
292
293 } else {
294 attainedWidth = renderDrawBuffer(repaintWidth,
283 h, 295 h,
284 binforx, 296 binforx,
285 binfory, 297 binfory,
286 usePeaksCache, 298 usePeaksCache,
287 rightToLeft, 299 rightToLeft,
288 timeConstrained); 300 timeConstrained);
301 }
289 302
290 if (attainedWidth == 0) return; 303 if (attainedWidth == 0) return;
291 304
292 // draw buffer is pixel resolution, no scaling factors or padding involved 305 // draw buffer is pixel resolution, no scaling factors or padding involved
293 306
574 } 587 }
575 588
576 return columnCount; 589 return columnCount;
577 } 590 }
578 591
592 int
593 Colour3DPlotRenderer::renderDrawBufferPeakFrequencies(LayerGeometryProvider *v,
594 int w, int h,
595 const vector<int> &binforx,
596 const vector<double> &binfory,
597 bool rightToLeft,
598 bool timeConstrained)
599 {
600 // Callers must have checked that the appropriate subset of
601 // Sources data members are set for the supplied flags (e.g. that
602 // fft model exists)
603
604 RenderTimer timer(timeConstrained ?
605 RenderTimer::FastRender :
606 RenderTimer::NoTimeout);
607
608 int minbin = int(binfory[0] + 0.0001);
609 int maxbin = int(binfory[h-1]);
610 if (minbin < 0) minbin = 0;
611 if (maxbin < 0) maxbin = minbin+1;
612
613 FFTModel *fft = m_sources.fft;
614
615 FFTModel::PeakSet peakfreqs;
616
617 int psx = -1;
618
619 int start = 0;
620 int finish = w;
621 int step = 1;
622
623 if (rightToLeft) {
624 start = w-1;
625 finish = -1;
626 step = -1;
627 }
628
629 int columnCount = 0;
630
631 vector<float> preparedColumn;
632
633 int modelWidth = fft->getWidth();
634 cerr << "modelWidth " << modelWidth << endl;
635
636 double minFreq = (double(minbin) * fft->getSampleRate()) / fft->getFFTSize();
637 double maxFreq = (double(maxbin) * fft->getSampleRate()) / fft->getFFTSize();
638
639 bool logarithmic = (m_params.binScale == LogBinScale);
640
641 for (int x = start; x != finish; x += step) {
642
643 // x is the on-canvas pixel coord; sx (later) will be the
644 // source column index
645
646 ++columnCount;
647
648 if (binforx[x] < 0) continue;
649
650 int sx0 = binforx[x];
651 int sx1 = sx0;
652 if (x+1 < w) sx1 = binforx[x+1];
653 if (sx0 < 0) sx0 = sx1 - 1;
654 if (sx0 < 0) continue;
655 if (sx1 <= sx0) sx1 = sx0 + 1;
656
657 vector<float> pixelPeakColumn;
658
659 for (int sx = sx0; sx < sx1; ++sx) {
660
661 if (sx < 0 || sx >= modelWidth) {
662 continue;
663 }
664
665 if (sx != psx) {
666
667 ColumnOp::Column fullColumn = fft->getColumn(sx);
668
669 ColumnOp::Column column =
670 vector<float>(fullColumn.data() + minbin,
671 fullColumn.data() + maxbin + 1);
672
673 //!!! fft scale if (m_colourScale != ColourScale::PhaseColourScale) {
674 // column = ColumnOp::fftScale(column, getFFTSize());
675 // }
676
677 //!!! extents recordColumnExtents(column,
678 // sx,
679 // overallMag,
680 // overallMagChanged);
681
682 //!!! if (m_colourScale != ColourScale::PhaseColourScale) {
683 column = ColumnOp::normalize(column, m_params.normalization);
684 //!!! }
685
686 preparedColumn = column;
687 //!!! gain? preparedColumn = ColumnOp::applyGain(column, m_params.gain);
688
689 psx = sx;
690 }
691
692 if (sx == sx0) {
693 pixelPeakColumn = preparedColumn;
694 peakfreqs = fft->getPeakFrequencies(FFTModel::AllPeaks, sx,
695 minbin, maxbin - 1);
696 } else {
697 for (int i = 0; in_range_for(pixelPeakColumn, i); ++i) {
698 pixelPeakColumn[i] = std::max(pixelPeakColumn[i],
699 preparedColumn[i]);
700 }
701 }
702 }
703
704 if (!pixelPeakColumn.empty()) {
705 for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
706 pi != peakfreqs.end(); ++pi) {
707
708 int bin = pi->first;
709 double freq = pi->second;
710
711 if (bin < minbin) continue;
712 if (bin > maxbin) break;
713
714 double value = pixelPeakColumn[bin - minbin];
715
716 double y = v->getYForFrequency
717 (freq, minFreq, maxFreq, logarithmic);
718
719 int iy = int(y + 0.5);
720 if (iy < 0 || iy >= h) continue;
721
722 m_drawBuffer.setPixel
723 (x,
724 iy,
725 m_params.colourScale.getPixel(value));
726 }
727 }
728
729 double fractionComplete = double(columnCount) / double(w);
730 if (timer.outOfTime(fractionComplete)) {
731 return columnCount;
732 }
733 }
734
735 return columnCount;
736 }
737
579 void 738 void
580 Colour3DPlotRenderer::recreateDrawBuffer(int w, int h) 739 Colour3DPlotRenderer::recreateDrawBuffer(int w, int h)
581 { 740 {
582 m_drawBuffer = QImage(w, h, QImage::Format_Indexed8); 741 m_drawBuffer = QImage(w, h, QImage::Format_Indexed8);
583 742