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);