Mercurial > hg > svgui
comparison layer/SpectrumLayer.cpp @ 1473:886c1cd48f9d by-id
Further layer updates for ModelById
author | Chris Cannam |
---|---|
date | Tue, 02 Jul 2019 11:49:52 +0100 |
parents | f2525e6cbdf1 |
children | e540aa5d89cd |
comparison
equal
deleted
inserted
replaced
1472:dbff4b290bf0 | 1473:886c1cd48f9d |
---|---|
31 #include <QPainter> | 31 #include <QPainter> |
32 #include <QTextStream> | 32 #include <QTextStream> |
33 | 33 |
34 | 34 |
35 SpectrumLayer::SpectrumLayer() : | 35 SpectrumLayer::SpectrumLayer() : |
36 m_originModel(nullptr), | |
37 m_channel(-1), | 36 m_channel(-1), |
38 m_channelSet(false), | 37 m_channelSet(false), |
39 m_windowSize(4096), | 38 m_windowSize(4096), |
40 m_windowType(HanningWindow), | 39 m_windowType(HanningWindow), |
41 m_windowHopLevel(3), | 40 m_windowHopLevel(3), |
54 setBinScale(LogBins); | 53 setBinScale(LogBins); |
55 } | 54 } |
56 | 55 |
57 SpectrumLayer::~SpectrumLayer() | 56 SpectrumLayer::~SpectrumLayer() |
58 { | 57 { |
59 Model *m = const_cast<Model *> | 58 ModelById::release(m_sliceableModel); |
60 (static_cast<const Model *>(m_sliceableModel)); | |
61 if (m) m->aboutToDelete(); | |
62 m_sliceableModel = nullptr; | |
63 delete m; | |
64 } | 59 } |
65 | 60 |
66 void | 61 void |
67 SpectrumLayer::setModel(ModelId modelId) | 62 SpectrumLayer::setModel(ModelId modelId) |
68 { | 63 { |
72 } | 67 } |
73 | 68 |
74 if (m_originModel == modelId) return; | 69 if (m_originModel == modelId) return; |
75 m_originModel = modelId; | 70 m_originModel = modelId; |
76 | 71 |
77 if (newModel) { | |
78 //... | |
79 } | |
80 | |
81 //!!! todo - all of this | |
82 | |
83 if (m_sliceableModel) { | |
84 Model *m = const_cast<Model *> | |
85 (static_cast<const Model *>(m_sliceableModel)); | |
86 m->aboutToDelete(); | |
87 setSliceableModel(nullptr); | |
88 delete m; | |
89 } | |
90 | |
91 m_newFFTNeeded = true; | 72 m_newFFTNeeded = true; |
92 | 73 |
93 emit layerParametersChanged(); | 74 emit layerParametersChanged(); |
94 } | 75 } |
95 | 76 |
110 } | 91 } |
111 | 92 |
112 void | 93 void |
113 SpectrumLayer::setupFFT() | 94 SpectrumLayer::setupFFT() |
114 { | 95 { |
115 if (m_sliceableModel) { | 96 ModelById::release(m_sliceableModel); |
116 Model *m = const_cast<Model *> | 97 m_sliceableModel = {}; |
117 (static_cast<const Model *>(m_sliceableModel)); | 98 |
118 m->aboutToDelete(); | 99 if (m_originModel.isNone()) { |
119 setSliceableModel(nullptr); | |
120 delete m; | |
121 } | |
122 | |
123 if (!m_originModel) { | |
124 return; | 100 return; |
125 } | 101 } |
126 | 102 |
127 int fftSize = getFFTSize(); | 103 int fftSize = getFFTSize(); |
128 | 104 |
129 FFTModel *newFFT = new FFTModel(m_originModel, | 105 auto newFFT = std::make_shared<FFTModel>(m_originModel, |
130 m_channel, | 106 m_channel, |
131 m_windowType, | 107 m_windowType, |
132 m_windowSize, | 108 m_windowSize, |
133 getWindowIncrement(), | 109 getWindowIncrement(), |
134 fftSize); | 110 fftSize); |
135 | 111 |
136 if (m_minbin == 0 && m_maxbin == 0) { | 112 if (m_minbin == 0 && m_maxbin == 0) { |
137 m_minbin = 1; | 113 m_minbin = 1; |
138 m_freqOfMinBin = double(m_minbin * newFFT->getSampleRate()) | 114 m_freqOfMinBin = double(m_minbin * newFFT->getSampleRate()) |
139 / getFFTSize(); | 115 / getFFTSize(); |
140 m_maxbin = newFFT->getHeight(); | 116 m_maxbin = newFFT->getHeight(); |
141 } | 117 } |
142 | 118 |
143 setSliceableModel(newFFT); | 119 ModelById::add(newFFT); |
120 setSliceableModel(newFFT->getId()); | |
144 | 121 |
145 m_biasCurve.clear(); | 122 m_biasCurve.clear(); |
146 for (int i = 0; i < fftSize; ++i) { | 123 for (int i = 0; i < fftSize; ++i) { |
147 // Scale by the window size, not the FFT size, because we | 124 // Scale by the window size, not the FFT size, because we |
148 // don't want to scale down by all the zero bins | 125 // don't want to scale down by all the zero bins |
409 } | 386 } |
410 | 387 |
411 double | 388 double |
412 SpectrumLayer::getBinForFrequency(double freq) const | 389 SpectrumLayer::getBinForFrequency(double freq) const |
413 { | 390 { |
414 if (!m_sliceableModel) return 0; | 391 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
415 double bin = (freq * getFFTSize()) / m_sliceableModel->getSampleRate(); | 392 (m_sliceableModel); |
393 if (!sliceableModel) return 0; | |
394 double bin = (freq * getFFTSize()) / sliceableModel->getSampleRate(); | |
416 return bin; | 395 return bin; |
417 } | 396 } |
418 | 397 |
419 double | 398 double |
420 SpectrumLayer::getBinForX(const LayerGeometryProvider *v, double x) const | 399 SpectrumLayer::getBinForX(const LayerGeometryProvider *v, double x) const |
421 { | 400 { |
422 if (!m_sliceableModel) return 0; | 401 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
402 (m_sliceableModel); | |
403 if (!sliceableModel) return 0; | |
423 double bin = getBinForFrequency(getFrequencyForX(v, x)); | 404 double bin = getBinForFrequency(getFrequencyForX(v, x)); |
424 return bin; | 405 return bin; |
425 } | 406 } |
426 | 407 |
427 double | 408 double |
428 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const | 409 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const |
429 { | 410 { |
430 if (!m_sliceableModel) return 0; | 411 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
412 (m_sliceableModel); | |
413 if (!sliceableModel) return 0; | |
431 | 414 |
432 double fmin = getFrequencyForBin(m_minbin); | 415 double fmin = getFrequencyForBin(m_minbin); |
433 double fmax = getFrequencyForBin(m_maxbin); | 416 double fmax = getFrequencyForBin(m_maxbin); |
434 | 417 |
435 double freq = getScalePointForX(v, x, fmin, fmax); | 418 double freq = getScalePointForX(v, x, fmin, fmax); |
437 } | 420 } |
438 | 421 |
439 double | 422 double |
440 SpectrumLayer::getFrequencyForBin(double bin) const | 423 SpectrumLayer::getFrequencyForBin(double bin) const |
441 { | 424 { |
442 if (!m_sliceableModel) return 0; | 425 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
443 double freq = (bin * m_sliceableModel->getSampleRate()) / getFFTSize(); | 426 (m_sliceableModel); |
427 if (!sliceableModel) return 0; | |
428 double freq = (bin * sliceableModel->getSampleRate()) / getFFTSize(); | |
444 return freq; | 429 return freq; |
445 } | 430 } |
446 | 431 |
447 double | 432 double |
448 SpectrumLayer::getXForBin(const LayerGeometryProvider *v, double bin) const | 433 SpectrumLayer::getXForBin(const LayerGeometryProvider *v, double bin) const |
449 { | 434 { |
450 if (!m_sliceableModel) return 0; | 435 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
436 (m_sliceableModel); | |
437 if (!sliceableModel) return 0; | |
451 double x = getXForFrequency(v, getFrequencyForBin(bin)); | 438 double x = getXForFrequency(v, getFrequencyForBin(bin)); |
452 return x; | 439 return x; |
453 } | 440 } |
454 | 441 |
455 double | 442 double |
456 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const | 443 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const |
457 { | 444 { |
458 if (!m_sliceableModel) return 0; | 445 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
446 (m_sliceableModel); | |
447 if (!sliceableModel) return 0; | |
459 | 448 |
460 double fmin = getFrequencyForBin(m_minbin); | 449 double fmin = getFrequencyForBin(m_minbin); |
461 double fmax = getFrequencyForBin(m_maxbin); | 450 double fmax = getFrequencyForBin(m_maxbin); |
462 double x = getXForScalePoint(v, freq, fmin, fmax); | 451 double x = getXForScalePoint(v, freq, fmin, fmax); |
463 | 452 |
481 | 470 |
482 if (m_energyScale == dBScale || m_energyScale == MeterScale) { | 471 if (m_energyScale == dBScale || m_energyScale == MeterScale) { |
483 | 472 |
484 if (value > 0.0) { | 473 if (value > 0.0) { |
485 value = 10.0 * log10(value); | 474 value = 10.0 * log10(value); |
486 if (value < m_threshold) value = m_threshold; | 475 if (value < m_threshold) { |
487 } else value = m_threshold; | 476 value = m_threshold; |
477 } | |
478 } else { | |
479 value = m_threshold; | |
480 } | |
488 | 481 |
489 unit = "dBV"; | 482 unit = "dBV"; |
490 | 483 |
491 } else { | 484 } else { |
492 unit = "V"; | 485 unit = "V"; |
518 | 511 |
519 int hoffset = 2; | 512 int hoffset = 2; |
520 if (m_binScale == LogBins) hoffset = 13; | 513 if (m_binScale == LogBins) hoffset = 13; |
521 | 514 |
522 int sw = getVerticalScaleWidth(v, false, paint); | 515 int sw = getVerticalScaleWidth(v, false, paint); |
516 | |
517 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested | |
518 // replacement (horizontalAdvance) was only added in Qt 5.11 | |
519 // which is too new for us | |
520 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
523 | 521 |
524 QRect value(sw, cursorPos.y() - paint.fontMetrics().ascent() - 2, | 522 QRect value(sw, cursorPos.y() - paint.fontMetrics().ascent() - 2, |
525 paint.fontMetrics().width("0.0000001 V") + 2, | 523 paint.fontMetrics().width("0.0000001 V") + 2, |
526 paint.fontMetrics().height()); | 524 paint.fontMetrics().height()); |
527 extents.push_back(value); | 525 extents.push_back(value); |
549 | 547 |
550 void | 548 void |
551 SpectrumLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, | 549 SpectrumLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, |
552 QPoint cursorPos) const | 550 QPoint cursorPos) const |
553 { | 551 { |
554 if (!m_sliceableModel) return; | 552 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
553 (m_sliceableModel); | |
554 if (!sliceableModel) return; | |
555 | 555 |
556 paint.save(); | 556 paint.save(); |
557 QFont fn = paint.font(); | 557 QFont fn = paint.font(); |
558 if (fn.pointSize() > 8) { | 558 if (fn.pointSize() > 8) { |
559 fn.setPointSize(fn.pointSize() - 1); | 559 fn.setPointSize(fn.pointSize() - 1); |
636 } | 636 } |
637 | 637 |
638 QString | 638 QString |
639 SpectrumLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const | 639 SpectrumLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const |
640 { | 640 { |
641 if (!m_sliceableModel) return ""; | 641 auto sliceableModel = ModelById::getAs<DenseThreeDimensionalModel> |
642 (m_sliceableModel); | |
643 if (!sliceableModel) return ""; | |
642 | 644 |
643 int minbin = 0, maxbin = 0, range = 0; | 645 int minbin = 0, maxbin = 0, range = 0; |
644 QString genericDesc = SliceLayer::getFeatureDescriptionAux | 646 QString genericDesc = SliceLayer::getFeatureDescriptionAux |
645 (v, p, false, minbin, maxbin, range); | 647 (v, p, false, minbin, maxbin, range); |
646 | 648 |
657 | 659 |
658 if (minvalue > maxvalue) std::swap(minvalue, maxvalue); | 660 if (minvalue > maxvalue) std::swap(minvalue, maxvalue); |
659 | 661 |
660 QString binstr; | 662 QString binstr; |
661 QString hzstr; | 663 QString hzstr; |
662 int minfreq = int(lrint((minbin * m_sliceableModel->getSampleRate()) / | 664 int minfreq = int(lrint((minbin * sliceableModel->getSampleRate()) / |
663 getFFTSize())); | 665 getFFTSize())); |
664 int maxfreq = int(lrint((std::max(maxbin, minbin) | 666 int maxfreq = int(lrint((std::max(maxbin, minbin) |
665 * m_sliceableModel->getSampleRate()) / | 667 * sliceableModel->getSampleRate()) / |
666 getFFTSize())); | 668 getFFTSize())); |
667 | 669 |
668 if (maxbin != minbin) { | 670 if (maxbin != minbin) { |
669 binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1); | 671 binstr = tr("%1 - %2").arg(minbin+1).arg(maxbin+1); |
670 } else { | 672 } else { |
704 dbstr = tr("%1").arg(mindbstr); | 706 dbstr = tr("%1").arg(mindbstr); |
705 } | 707 } |
706 | 708 |
707 QString description; | 709 QString description; |
708 | 710 |
709 if (range > int(m_sliceableModel->getResolution())) { | 711 if (range > int(sliceableModel->getResolution())) { |
710 description = tr("%1\nBin:\t%2 (%3)\n%4 value:\t%5\ndB:\t%6") | 712 description = tr("%1\nBin:\t%2 (%3)\n%4 value:\t%5\ndB:\t%6") |
711 .arg(genericDesc) | 713 .arg(genericDesc) |
712 .arg(binstr) | 714 .arg(binstr) |
713 .arg(hzstr) | 715 .arg(hzstr) |
714 .arg(m_samplingMode == NearestSample ? tr("First") : | 716 .arg(m_samplingMode == NearestSample ? tr("First") : |
728 } | 730 } |
729 | 731 |
730 void | 732 void |
731 SpectrumLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 733 SpectrumLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
732 { | 734 { |
733 if (!m_originModel || !m_originModel->isOK() || | 735 auto originModel = ModelById::get(m_originModel); |
734 !m_originModel->isReady()) { | 736 if (!originModel || !originModel->isOK() || !originModel->isReady()) { |
735 SVDEBUG << "SpectrumLayer::paint: no origin model, or origin model not OK or not ready" << endl; | 737 SVDEBUG << "SpectrumLayer::paint: no origin model, or origin model not OK or not ready" << endl; |
736 return; | 738 return; |
737 } | 739 } |
738 | 740 |
739 if (m_newFFTNeeded) { | 741 if (m_newFFTNeeded) { |
740 SVDEBUG << "SpectrumLayer::paint: new FFT needed, calling setupFFT" << endl; | 742 SVDEBUG << "SpectrumLayer::paint: new FFT needed, calling setupFFT" << endl; |
741 const_cast<SpectrumLayer *>(this)->setupFFT(); //ugh | 743 const_cast<SpectrumLayer *>(this)->setupFFT(); //ugh |
742 } | 744 } |
743 | 745 |
744 FFTModel *fft = dynamic_cast<FFTModel *> | 746 auto fft = ModelById::getAs<FFTModel>(m_sliceableModel); |
745 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); | 747 if (!fft) return; |
746 | 748 |
747 double thresh = (pow(10, -6) / m_gain) * (getFFTSize() / 2.0); // -60dB adj | 749 double thresh = (pow(10, -6) / m_gain) * (getFFTSize() / 2.0); // -60dB adj |
748 | 750 |
749 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; | 751 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; |
750 int scaleHeight = getHorizontalScaleHeight(v, paint); | 752 int scaleHeight = getHorizontalScaleHeight(v, paint); |