comparison layer/SpectrumLayer.cpp @ 1282:f90a3c2f2930

Merge from branch horizontal-scale
author Chris Cannam
date Thu, 03 May 2018 15:24:14 +0100
parents fc9d9f1103fa
children d79e21855aef
comparison
equal deleted inserted replaced
1279:a04f1012fca2 1282:f90a3c2f2930
23 #include "base/Pitch.h" 23 #include "base/Pitch.h"
24 #include "base/Strings.h" 24 #include "base/Strings.h"
25 25
26 #include "ColourMapper.h" 26 #include "ColourMapper.h"
27 #include "PaintAssistant.h" 27 #include "PaintAssistant.h"
28 #include "PianoScale.h"
29 #include "HorizontalFrequencyScale.h"
28 30
29 #include <QPainter> 31 #include <QPainter>
30 #include <QTextStream> 32 #include <QTextStream>
31 33
32 34
300 double 302 double
301 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const 303 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const
302 { 304 {
303 if (!m_sliceableModel) return 0; 305 if (!m_sliceableModel) return 0;
304 double bin = getBinForX(v, x); 306 double bin = getBinForX(v, x);
307 // we assume the frequency of a bin corresponds to the centre of
308 // its visual range
309 bin -= 0.5;
305 return (m_sliceableModel->getSampleRate() * bin) / 310 return (m_sliceableModel->getSampleRate() * bin) /
306 (m_sliceableModel->getHeight() * 2); 311 (m_sliceableModel->getHeight() * 2);
307 } 312 }
308 313
309 double 314 double
310 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const 315 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const
311 { 316 {
312 if (!m_sliceableModel) return 0; 317 if (!m_sliceableModel) return 0;
313 double bin = (freq * m_sliceableModel->getHeight() * 2) / 318 double bin = (freq * m_sliceableModel->getHeight() * 2) /
314 m_sliceableModel->getSampleRate(); 319 m_sliceableModel->getSampleRate();
320 // we want the centre of the bin range
321 bin += 0.5;
315 return getXForBin(v, bin); 322 return getXForBin(v, bin);
316 } 323 }
317 324
318 bool 325 bool
319 SpectrumLayer::getXScaleValue(const LayerGeometryProvider *v, int x, 326 SpectrumLayer::getXScaleValue(const LayerGeometryProvider *v, int x,
596 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); 603 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel));
597 604
598 double thresh = (pow(10, -6) / m_gain) * (m_windowSize / 2.0); // -60dB adj 605 double thresh = (pow(10, -6) / m_gain) * (m_windowSize / 2.0); // -60dB adj
599 606
600 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; 607 int xorigin = getVerticalScaleWidth(v, false, paint) + 1;
601 int w = v->getPaintWidth() - xorigin - 1; 608 int scaleHeight = getHorizontalScaleHeight(v, paint);
602
603 int pkh = int(paint.fontMetrics().height() * 0.7 + 0.5);
604 if (pkh < 10) pkh = 10;
605
606 paint.save();
607 609
608 if (fft && m_showPeaks) { 610 if (fft && m_showPeaks) {
609 611
610 // draw peak lines 612 // draw peak lines
611
612 // SVDEBUG << "Showing peaks..." << endl;
613 613
614 int col = int(v->getCentreFrame() / fft->getResolution()); 614 int col = int(v->getCentreFrame() / fft->getResolution());
615 615
616 paint.save(); 616 paint.save();
617 paint.setRenderHint(QPainter::Antialiasing, false); 617 paint.setRenderHint(QPainter::Antialiasing, false);
618 paint.setPen(QColor(160, 160, 160)); //!!! 618
619 619 ColourMapper mapper =
620 hasLightBackground() ?
621 ColourMapper(ColourMapper::BlackOnWhite, 0, 1) :
622 ColourMapper(ColourMapper::WhiteOnBlack, 0, 1);
623
620 int peakminbin = 0; 624 int peakminbin = 0;
621 int peakmaxbin = fft->getHeight() - 1; 625 int peakmaxbin = fft->getHeight() - 1;
622 double peakmaxfreq = Pitch::getFrequencyForPitch(128); 626 double peakmaxfreq = Pitch::getFrequencyForPitch(128);
623 peakmaxbin = int(((peakmaxfreq * fft->getHeight() * 2) / fft->getSampleRate())); 627 peakmaxbin = int(((peakmaxfreq * fft->getHeight() * 2) / fft->getSampleRate()));
624 628
625 FFTModel::PeakSet peaks = fft->getPeakFrequencies 629 FFTModel::PeakSet peaks = fft->getPeakFrequencies
626 (FFTModel::MajorPitchAdaptivePeaks, col, peakminbin, peakmaxbin); 630 (FFTModel::MajorPitchAdaptivePeaks, col, peakminbin, peakmaxbin);
627 631
628 ColourMapper mapper(ColourMapper::BlackOnWhite, 0, 1);
629
630 BiasCurve curve; 632 BiasCurve curve;
631 getBiasCurve(curve); 633 getBiasCurve(curve);
632 int cs = int(curve.size()); 634 int cs = int(curve.size());
633 635
634 std::vector<double> values; 636 std::vector<double> values;
654 656
655 double norm = 0.f; 657 double norm = 0.f;
656 (void)getYForValue(v, values[bin], norm); // don't need return value, need norm 658 (void)getYForValue(v, values[bin], norm); // don't need return value, need norm
657 659
658 paint.setPen(mapper.map(norm)); 660 paint.setPen(mapper.map(norm));
659 paint.drawLine(x, 0, x, v->getPaintHeight() - scaleh - pkh - 1); 661 paint.drawLine(x, 0, x, v->getPaintHeight() - scaleHeight - 1);
660 } 662 }
661 663
662 paint.restore(); 664 paint.restore();
663 } 665 }
664 666
667 paint.save();
668
665 SliceLayer::paint(v, paint, rect); 669 SliceLayer::paint(v, paint, rect);
666 670
671 paintHorizontalScale(v, paint, xorigin);
672
673 paint.restore();
674 }
675
676 int
677 SpectrumLayer::getHorizontalScaleHeight(LayerGeometryProvider *v,
678 QPainter &paint) const
679 {
680 int pkh = int(paint.fontMetrics().height() * 0.7 + 0.5);
681 if (pkh < 10) pkh = 10;
682
683 int scaleh = HorizontalFrequencyScale().getHeight(v, paint);
684
685 return pkh + scaleh;
686 }
687
688 void
689 SpectrumLayer::paintHorizontalScale(LayerGeometryProvider *v,
690 QPainter &paint,
691 int xorigin) const
692 {
667 //!!! All of this stuff relating to depicting frequencies 693 //!!! All of this stuff relating to depicting frequencies
668 // (keyboard, crosshairs etc) should be applicable to any slice 694 // (keyboard, crosshairs etc) should be applicable to any slice
669 // layer whose model has a vertical scale unit of Hz. However, 695 // layer whose model has a vertical scale unit of Hz. However,
670 // the dense 3d model at the moment doesn't record its vertical 696 // the dense 3d model at the moment doesn't record its vertical
671 // scale unit -- we need to fix that and hoist this code as 697 // scale unit -- we need to fix that and hoist this code as
672 // appropriate. Same really goes for any code in SpectrogramLayer 698 // appropriate. Same really goes for any code in SpectrogramLayer
673 // that could be relevant to Colour3DPlotLayer with unit Hz, but 699 // that could be relevant to Colour3DPlotLayer with unit Hz, but
674 // that's a bigger proposition. 700 // that's a bigger proposition.
675 701
676 int h = v->getPaintHeight(); 702 if (!v->getViewManager()->shouldShowHorizontalValueScale()) {
703 return;
704 }
705
706 int totalScaleHeight = getHorizontalScaleHeight(v, paint); // inc piano
707 int freqScaleHeight = HorizontalFrequencyScale().getHeight(v, paint);
708 int paintHeight = v->getPaintHeight();
709 int paintWidth = v->getPaintWidth();
677 710
678 PianoScale().paintPianoHorizontal 711 PianoScale().paintPianoHorizontal
679 (v, this, paint, QRect(xorigin, h - pkh - 1, w + xorigin, pkh)); 712 (v, this, paint,
680 713 QRect(xorigin, paintHeight - totalScaleHeight - 1,
681 paint.restore(); 714 paintWidth - 1, totalScaleHeight - freqScaleHeight));
715
716 int scaleLeft = int(getXForBin(v, 1));
717
718 paint.drawLine(int(getXForBin(v, 0)), paintHeight - freqScaleHeight,
719 scaleLeft, paintHeight - freqScaleHeight);
720
721 QString hz = tr("Hz");
722 int hzw = paint.fontMetrics().width(hz);
723 if (scaleLeft > hzw + 5) {
724 paint.drawText
725 (scaleLeft - hzw - 5,
726 paintHeight - freqScaleHeight + paint.fontMetrics().ascent() + 5,
727 hz);
728 }
729
730 HorizontalFrequencyScale().paintScale
731 (v, this, paint,
732 QRect(scaleLeft, paintHeight - freqScaleHeight,
733 paintWidth, totalScaleHeight),
734 m_binScale == LogBins);
682 } 735 }
683 736
684 void 737 void
685 SpectrumLayer::getBiasCurve(BiasCurve &curve) const 738 SpectrumLayer::getBiasCurve(BiasCurve &curve) const
686 { 739 {