Mercurial > hg > svgui
comparison layer/SpectrumLayer.cpp @ 1216:dc2af6616c83
Merge from branch 3.0-integration
author | Chris Cannam |
---|---|
date | Fri, 13 Jan 2017 10:29:50 +0000 |
parents | 1badacff7ab2 |
children | ff97318e993c |
comparison
equal
deleted
inserted
replaced
1048:e8102ff5573b | 1216:dc2af6616c83 |
---|---|
19 #include "view/View.h" | 19 #include "view/View.h" |
20 #include "base/AudioLevel.h" | 20 #include "base/AudioLevel.h" |
21 #include "base/Preferences.h" | 21 #include "base/Preferences.h" |
22 #include "base/RangeMapper.h" | 22 #include "base/RangeMapper.h" |
23 #include "base/Pitch.h" | 23 #include "base/Pitch.h" |
24 #include "base/Strings.h" | |
25 | |
24 #include "ColourMapper.h" | 26 #include "ColourMapper.h" |
27 #include "PaintAssistant.h" | |
25 | 28 |
26 #include <QPainter> | 29 #include <QPainter> |
27 #include <QTextStream> | 30 #include <QTextStream> |
28 | 31 |
29 | 32 |
110 FFTModel *newFFT = new FFTModel(m_originModel, | 113 FFTModel *newFFT = new FFTModel(m_originModel, |
111 m_channel, | 114 m_channel, |
112 m_windowType, | 115 m_windowType, |
113 m_windowSize, | 116 m_windowSize, |
114 getWindowIncrement(), | 117 getWindowIncrement(), |
115 m_windowSize, | 118 m_windowSize); |
116 false, | |
117 StorageAdviser::Criteria | |
118 (StorageAdviser::SpeedCritical | | |
119 StorageAdviser::FrequentLookupLikely)); | |
120 | 119 |
121 setSliceableModel(newFFT); | 120 setSliceableModel(newFFT); |
122 | 121 |
123 m_biasCurve.clear(); | 122 m_biasCurve.clear(); |
124 for (int i = 0; i < m_windowSize; ++i) { | 123 for (int i = 0; i < m_windowSize; ++i) { |
125 m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); | 124 m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); |
126 } | 125 } |
127 | |
128 newFFT->resume(); | |
129 | 126 |
130 m_newFFTNeeded = false; | 127 m_newFFTNeeded = false; |
131 } | 128 } |
132 | 129 |
133 Layer::PropertyList | 130 Layer::PropertyList |
384 | 381 |
385 return x; | 382 return x; |
386 } | 383 } |
387 | 384 |
388 bool | 385 bool |
389 SpectrumLayer::getXScaleValue(const View *v, int x, | 386 SpectrumLayer::getXScaleValue(const LayerGeometryProvider *v, int x, |
390 double &value, QString &unit) const | 387 double &value, QString &unit) const |
391 { | 388 { |
392 if (m_xorigins.find(v) == m_xorigins.end()) return false; | 389 if (m_xorigins.find(v) == m_xorigins.end()) return false; |
393 int xorigin = m_xorigins.find(v)->second; | 390 int xorigin = m_xorigins.find(v)->second; |
394 value = getFrequencyForX(x - xorigin, v->width() - xorigin - 1); | 391 value = getFrequencyForX(x - xorigin, v->getPaintWidth() - xorigin - 1); |
395 unit = "Hz"; | 392 unit = "Hz"; |
396 return true; | 393 return true; |
397 } | 394 } |
398 | 395 |
399 bool | 396 bool |
400 SpectrumLayer::getYScaleValue(const View *v, int y, | 397 SpectrumLayer::getYScaleValue(const LayerGeometryProvider *v, int y, |
401 double &value, QString &unit) const | 398 double &value, QString &unit) const |
402 { | 399 { |
403 value = getValueForY(y, v); | 400 value = getValueForY(y, v); |
404 | 401 |
405 if (m_energyScale == dBScale || m_energyScale == MeterScale) { | 402 if (m_energyScale == dBScale || m_energyScale == MeterScale) { |
417 | 414 |
418 return true; | 415 return true; |
419 } | 416 } |
420 | 417 |
421 bool | 418 bool |
422 SpectrumLayer::getYScaleDifference(const View *v, int y0, int y1, | 419 SpectrumLayer::getYScaleDifference(const LayerGeometryProvider *v, int y0, int y1, |
423 double &diff, QString &unit) const | 420 double &diff, QString &unit) const |
424 { | 421 { |
425 bool rv = SliceLayer::getYScaleDifference(v, y0, y1, diff, unit); | 422 bool rv = SliceLayer::getYScaleDifference(v, y0, y1, diff, unit); |
426 if (rv && (unit == "dBV")) unit = "dB"; | 423 if (rv && (unit == "dBV")) unit = "dB"; |
427 return rv; | 424 return rv; |
428 } | 425 } |
429 | 426 |
430 | 427 |
431 bool | 428 bool |
432 SpectrumLayer::getCrosshairExtents(View *v, QPainter &paint, | 429 SpectrumLayer::getCrosshairExtents(LayerGeometryProvider *v, QPainter &paint, |
433 QPoint cursorPos, | 430 QPoint cursorPos, |
434 std::vector<QRect> &extents) const | 431 std::vector<QRect> &extents) const |
435 { | 432 { |
436 QRect vertical(cursorPos.x(), cursorPos.y(), 1, v->height() - cursorPos.y()); | 433 QRect vertical(cursorPos.x(), cursorPos.y(), 1, v->getPaintHeight() - cursorPos.y()); |
437 extents.push_back(vertical); | 434 extents.push_back(vertical); |
438 | 435 |
439 QRect horizontal(0, cursorPos.y(), v->width(), 12); | 436 QRect horizontal(0, cursorPos.y(), v->getPaintWidth(), 12); |
440 extents.push_back(horizontal); | 437 extents.push_back(horizontal); |
441 | 438 |
442 int hoffset = 2; | 439 int hoffset = 2; |
443 if (m_binScale == LogBins) hoffset = 13; | 440 if (m_binScale == LogBins) hoffset = 13; |
444 | 441 |
453 paint.fontMetrics().width("-80.000 dBV") + 2, | 450 paint.fontMetrics().width("-80.000 dBV") + 2, |
454 paint.fontMetrics().height()); | 451 paint.fontMetrics().height()); |
455 extents.push_back(log); | 452 extents.push_back(log); |
456 | 453 |
457 QRect freq(cursorPos.x(), | 454 QRect freq(cursorPos.x(), |
458 v->height() - paint.fontMetrics().height() - hoffset, | 455 v->getPaintHeight() - paint.fontMetrics().height() - hoffset, |
459 paint.fontMetrics().width("123456 Hz") + 2, | 456 paint.fontMetrics().width("123456 Hz") + 2, |
460 paint.fontMetrics().height()); | 457 paint.fontMetrics().height()); |
461 extents.push_back(freq); | 458 extents.push_back(freq); |
462 | 459 |
463 int w(paint.fontMetrics().width("C#10+50c") + 2); | 460 int w(paint.fontMetrics().width("C#10+50c") + 2); |
464 QRect pitch(cursorPos.x() - w, | 461 QRect pitch(cursorPos.x() - w, |
465 v->height() - paint.fontMetrics().height() - hoffset, | 462 v->getPaintHeight() - paint.fontMetrics().height() - hoffset, |
466 w, | 463 w, |
467 paint.fontMetrics().height()); | 464 paint.fontMetrics().height()); |
468 extents.push_back(pitch); | 465 extents.push_back(pitch); |
469 | 466 |
470 return true; | 467 return true; |
471 } | 468 } |
472 | 469 |
473 void | 470 void |
474 SpectrumLayer::paintCrosshairs(View *v, QPainter &paint, | 471 SpectrumLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, |
475 QPoint cursorPos) const | 472 QPoint cursorPos) const |
476 { | 473 { |
477 if (!m_sliceableModel) return; | 474 if (!m_sliceableModel) return; |
478 | 475 |
479 paint.save(); | 476 paint.save(); |
485 | 482 |
486 ColourMapper mapper(m_colourMap, 0, 1); | 483 ColourMapper mapper(m_colourMap, 0, 1); |
487 paint.setPen(mapper.getContrastingColour()); | 484 paint.setPen(mapper.getContrastingColour()); |
488 | 485 |
489 int xorigin = m_xorigins[v]; | 486 int xorigin = m_xorigins[v]; |
490 int w = v->width() - xorigin - 1; | 487 int w = v->getPaintWidth() - xorigin - 1; |
491 | 488 |
492 paint.drawLine(xorigin, cursorPos.y(), v->width(), cursorPos.y()); | 489 paint.drawLine(xorigin, cursorPos.y(), v->getPaintWidth(), cursorPos.y()); |
493 paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->height()); | 490 paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->getPaintHeight()); |
494 | 491 |
495 double fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); | 492 double fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); |
496 | 493 |
497 int hoffset = 2; | 494 int hoffset = 2; |
498 if (m_binScale == LogBins) hoffset = 13; | 495 if (m_binScale == LogBins) hoffset = 13; |
499 | 496 |
500 v->drawVisibleText(paint, | 497 PaintAssistant::drawVisibleText(v, paint, |
501 cursorPos.x() + 2, | 498 cursorPos.x() + 2, |
502 v->height() - 2 - hoffset, | 499 v->getPaintHeight() - 2 - hoffset, |
503 QString("%1 Hz").arg(fundamental), | 500 QString("%1 Hz").arg(fundamental), |
504 View::OutlinedText); | 501 PaintAssistant::OutlinedText); |
505 | 502 |
506 if (Pitch::isFrequencyInMidiRange(fundamental)) { | 503 if (Pitch::isFrequencyInMidiRange(fundamental)) { |
507 QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental); | 504 QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental); |
508 v->drawVisibleText(paint, | 505 PaintAssistant::drawVisibleText(v, paint, |
509 cursorPos.x() - paint.fontMetrics().width(pitchLabel) - 2, | 506 cursorPos.x() - paint.fontMetrics().width(pitchLabel) - 2, |
510 v->height() - 2 - hoffset, | 507 v->getPaintHeight() - 2 - hoffset, |
511 pitchLabel, | 508 pitchLabel, |
512 View::OutlinedText); | 509 PaintAssistant::OutlinedText); |
513 } | 510 } |
514 | 511 |
515 double value = getValueForY(cursorPos.y(), v); | 512 double value = getValueForY(cursorPos.y(), v); |
516 double thresh = m_threshold; | 513 double thresh = m_threshold; |
517 double db = thresh; | 514 double db = thresh; |
518 if (value > 0.0) db = 10.0 * log10(value); | 515 if (value > 0.0) db = 10.0 * log10(value); |
519 if (db < thresh) db = thresh; | 516 if (db < thresh) db = thresh; |
520 | 517 |
521 v->drawVisibleText(paint, | 518 PaintAssistant::drawVisibleText(v, paint, |
522 xorigin + 2, | 519 xorigin + 2, |
523 cursorPos.y() - 2, | 520 cursorPos.y() - 2, |
524 QString("%1 V").arg(value), | 521 QString("%1 V").arg(value), |
525 View::OutlinedText); | 522 PaintAssistant::OutlinedText); |
526 | 523 |
527 v->drawVisibleText(paint, | 524 PaintAssistant::drawVisibleText(v, paint, |
528 xorigin + 2, | 525 xorigin + 2, |
529 cursorPos.y() + 2 + paint.fontMetrics().ascent(), | 526 cursorPos.y() + 2 + paint.fontMetrics().ascent(), |
530 QString("%1 dBV").arg(db), | 527 QString("%1 dBV").arg(db), |
531 View::OutlinedText); | 528 PaintAssistant::OutlinedText); |
532 | 529 |
533 int harmonic = 2; | 530 int harmonic = 2; |
534 | 531 |
535 while (harmonic < 100) { | 532 while (harmonic < 100) { |
536 | 533 |
537 int hx = int(lrint(getXForFrequency(fundamental * harmonic, w))); | 534 int hx = int(lrint(getXForFrequency(fundamental * harmonic, w))); |
538 hx += xorigin; | 535 hx += xorigin; |
539 | 536 |
540 if (hx < xorigin || hx > v->width()) break; | 537 if (hx < xorigin || hx > v->getPaintWidth()) break; |
541 | 538 |
542 int len = 7; | 539 int len = 7; |
543 | 540 |
544 if (harmonic % 2 == 0) { | 541 if (harmonic % 2 == 0) { |
545 if (harmonic % 4 == 0) { | 542 if (harmonic % 4 == 0) { |
559 | 556 |
560 paint.restore(); | 557 paint.restore(); |
561 } | 558 } |
562 | 559 |
563 QString | 560 QString |
564 SpectrumLayer::getFeatureDescription(View *v, QPoint &p) const | 561 SpectrumLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const |
565 { | 562 { |
566 if (!m_sliceableModel) return ""; | 563 if (!m_sliceableModel) return ""; |
567 | 564 |
568 int minbin = 0, maxbin = 0, range = 0; | 565 int minbin = 0, maxbin = 0, range = 0; |
569 QString genericDesc = SliceLayer::getFeatureDescriptionAux | 566 QString genericDesc = SliceLayer::getFeatureDescriptionAux |
609 double mindb = AudioLevel::multiplier_to_dB(minvalue); | 606 double mindb = AudioLevel::multiplier_to_dB(minvalue); |
610 double maxdb = AudioLevel::multiplier_to_dB(maxvalue); | 607 double maxdb = AudioLevel::multiplier_to_dB(maxvalue); |
611 QString mindbstr; | 608 QString mindbstr; |
612 QString maxdbstr; | 609 QString maxdbstr; |
613 if (mindb == AudioLevel::DB_FLOOR) { | 610 if (mindb == AudioLevel::DB_FLOOR) { |
614 mindbstr = tr("-Inf"); | 611 mindbstr = Strings::minus_infinity; |
615 } else { | 612 } else { |
616 mindbstr = QString("%1").arg(lrint(mindb)); | 613 mindbstr = QString("%1").arg(lrint(mindb)); |
617 } | 614 } |
618 if (maxdb == AudioLevel::DB_FLOOR) { | 615 if (maxdb == AudioLevel::DB_FLOOR) { |
619 maxdbstr = tr("-Inf"); | 616 maxdbstr = Strings::minus_infinity; |
620 } else { | 617 } else { |
621 maxdbstr = QString("%1").arg(lrint(maxdb)); | 618 maxdbstr = QString("%1").arg(lrint(maxdb)); |
622 } | 619 } |
623 if (lrint(mindb) != lrint(maxdb)) { | 620 if (lrint(mindb) != lrint(maxdb)) { |
624 dbstr = tr("%1 - %2").arg(mindbstr).arg(maxdbstr); | 621 dbstr = tr("%1 - %2").arg(mindbstr).arg(maxdbstr); |
648 | 645 |
649 return description; | 646 return description; |
650 } | 647 } |
651 | 648 |
652 void | 649 void |
653 SpectrumLayer::paint(View *v, QPainter &paint, QRect rect) const | 650 SpectrumLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
654 { | 651 { |
655 if (!m_originModel || !m_originModel->isOK() || | 652 if (!m_originModel || !m_originModel->isOK() || |
656 !m_originModel->isReady()) { | 653 !m_originModel->isReady()) { |
657 SVDEBUG << "SpectrumLayer::paint: no origin model, or origin model not OK or not ready" << endl; | 654 SVDEBUG << "SpectrumLayer::paint: no origin model, or origin model not OK or not ready" << endl; |
658 return; | 655 return; |
667 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); | 664 (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); |
668 | 665 |
669 double thresh = (pow(10, -6) / m_gain) * (m_windowSize / 2.0); // -60dB adj | 666 double thresh = (pow(10, -6) / m_gain) * (m_windowSize / 2.0); // -60dB adj |
670 | 667 |
671 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; | 668 int xorigin = getVerticalScaleWidth(v, false, paint) + 1; |
672 int w = v->width() - xorigin - 1; | 669 int w = v->getPaintWidth() - xorigin - 1; |
673 | 670 |
674 int pkh = 0; | 671 int pkh = 0; |
675 //!!! if (m_binScale == LogBins) { | 672 //!!! if (m_binScale == LogBins) { |
676 pkh = 10; | 673 pkh = 10; |
677 //!!! } | 674 //!!! } |
727 | 724 |
728 double norm = 0.f; | 725 double norm = 0.f; |
729 (void)getYForValue(values[bin], v, norm); // don't need return value, need norm | 726 (void)getYForValue(values[bin], v, norm); // don't need return value, need norm |
730 | 727 |
731 paint.setPen(mapper.map(norm)); | 728 paint.setPen(mapper.map(norm)); |
732 paint.drawLine(xorigin + x, 0, xorigin + x, v->height() - pkh - 1); | 729 paint.drawLine(xorigin + x, 0, xorigin + x, v->getPaintHeight() - pkh - 1); |
733 } | 730 } |
734 | 731 |
735 paint.restore(); | 732 paint.restore(); |
736 } | 733 } |
737 | 734 |
747 //proposition. | 744 //proposition. |
748 | 745 |
749 // if (m_binScale == LogBins) { | 746 // if (m_binScale == LogBins) { |
750 | 747 |
751 // int pkh = 10; | 748 // int pkh = 10; |
752 int h = v->height(); | 749 int h = v->getPaintHeight(); |
753 | 750 |
754 // piano keyboard | 751 // piano keyboard |
755 //!!! should be in a new paintHorizontalScale()? | 752 //!!! should be in a new paintHorizontalScale()? |
756 // nice to have a piano keyboard class, of course | 753 // nice to have a piano keyboard class, of course |
757 | 754 |