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