comparison layer/WaveformLayer.cpp @ 1486:ac0a8addabcf

Merge from branch by-id
author Chris Cannam
date Wed, 17 Jul 2019 14:25:16 +0100
parents 36ad3cdabf55
children 1ccb64bfb22b
comparison
equal deleted inserted replaced
1468:de41a11cabc2 1486:ac0a8addabcf
39 using std::vector; 39 using std::vector;
40 40
41 41
42 WaveformLayer::WaveformLayer() : 42 WaveformLayer::WaveformLayer() :
43 SingleColourLayer(), 43 SingleColourLayer(),
44 m_model(nullptr),
45 m_gain(1.0f), 44 m_gain(1.0f),
46 m_autoNormalize(false), 45 m_autoNormalize(false),
47 m_showMeans(true), 46 m_showMeans(true),
48 m_channelMode(SeparateChannels), 47 m_channelMode(SeparateChannels),
49 m_channel(-1), 48 m_channel(-1),
58 WaveformLayer::~WaveformLayer() 57 WaveformLayer::~WaveformLayer()
59 { 58 {
60 delete m_cache; 59 delete m_cache;
61 } 60 }
62 61
63 void 62 const ZoomConstraint *
64 WaveformLayer::setModel(const RangeSummarisableTimeValueModel *model) 63 WaveformLayer::getZoomConstraint() const
65 { 64 {
65 auto model = ModelById::get(m_model);
66 if (model) return model->getZoomConstraint();
67 else return nullptr;
68 }
69
70 void
71 WaveformLayer::setModel(ModelId modelId)
72 {
73 auto oldModel = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
74 auto newModel = ModelById::getAs<RangeSummarisableTimeValueModel>(modelId);
75
76 if (!modelId.isNone() && !newModel) {
77 throw std::logic_error("Not a RangeSummarisableTimeValueModel");
78 }
79
80 if (m_model == modelId) return;
81 m_model = modelId;
82
83 m_cacheValid = false;
84
66 bool channelsChanged = false; 85 bool channelsChanged = false;
67 if (m_channel == -1) { 86 if (m_channel == -1) {
68 if (!m_model) { 87 if (!oldModel) {
69 if (model) { 88 if (newModel) {
70 channelsChanged = true; 89 channelsChanged = true;
71 } 90 }
72 } else { 91 } else {
73 if (model && 92 if (newModel &&
74 m_model->getChannelCount() != model->getChannelCount()) { 93 oldModel->getChannelCount() != newModel->getChannelCount()) {
75 channelsChanged = true; 94 channelsChanged = true;
76 } 95 }
77 } 96 }
78 } 97 }
79 98
80 m_model = model; 99 if (newModel) {
81 m_cacheValid = false; 100 connectSignals(m_model);
82 if (!m_model || !m_model->isOK()) return; 101 }
83 102
84 connectSignals(m_model);
85
86 emit modelReplaced(); 103 emit modelReplaced();
87 104
88 if (channelsChanged) emit layerParametersChanged(); 105 if (channelsChanged) emit layerParametersChanged();
89 } 106 }
90 107
94 PropertyList list = SingleColourLayer::getProperties(); 111 PropertyList list = SingleColourLayer::getProperties();
95 list.push_back("Scale"); 112 list.push_back("Scale");
96 list.push_back("Gain"); 113 list.push_back("Gain");
97 list.push_back("Normalize Visible Area"); 114 list.push_back("Normalize Visible Area");
98 115
99 if (m_model && m_model->getChannelCount() > 1 && m_channel == -1) { 116 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
117 if (model && model->getChannelCount() > 1 && m_channel == -1) {
100 list.push_back("Channels"); 118 list.push_back("Channels");
101 } 119 }
102 120
103 return list; 121 return list;
104 } 122 }
321 339
322 int 340 int
323 WaveformLayer::getCompletion(LayerGeometryProvider *) const 341 WaveformLayer::getCompletion(LayerGeometryProvider *) const
324 { 342 {
325 int completion = 100; 343 int completion = 100;
326 if (!m_model || !m_model->isOK()) return completion; 344 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
327 if (m_model->isReady(&completion)) return 100; 345 if (!model || !model->isOK()) return completion;
346 if (model->isReady(&completion)) return 100;
328 return completion; 347 return completion;
329 } 348 }
330 349
331 bool 350 bool
332 WaveformLayer::getValueExtents(double &min, double &max, 351 WaveformLayer::getValueExtents(double &min, double &max,
359 int 378 int
360 WaveformLayer::getChannelArrangement(int &min, int &max, 379 WaveformLayer::getChannelArrangement(int &min, int &max,
361 bool &merging, bool &mixing) 380 bool &merging, bool &mixing)
362 const 381 const
363 { 382 {
364 if (!m_model || !m_model->isOK()) return 0; 383 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
365 384 if (!model || !model->isOK()) return 0;
366 int channels = m_model->getChannelCount(); 385
386 int channels = model->getChannelCount();
367 if (channels == 0) return 0; 387 if (channels == 0) return 0;
368 388
369 int rawChannels = channels; 389 int rawChannels = channels;
370 390
371 if (m_channel == -1) { 391 if (m_channel == -1) {
404 bool 424 bool
405 WaveformLayer::getSourceFramesForX(LayerGeometryProvider *v, 425 WaveformLayer::getSourceFramesForX(LayerGeometryProvider *v,
406 int x, int modelZoomLevel, 426 int x, int modelZoomLevel,
407 sv_frame_t &f0, sv_frame_t &f1) const 427 sv_frame_t &f0, sv_frame_t &f1) const
408 { 428 {
429 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
430 if (!model) return false;
431
409 sv_frame_t viewFrame = v->getFrameForX(x); 432 sv_frame_t viewFrame = v->getFrameForX(x);
410 if (viewFrame < 0) { 433 if (viewFrame < 0) {
411 f0 = 0; 434 f0 = 0;
412 f1 = 0; 435 f1 = 0;
413 return false; 436 return false;
424 f1 = viewFrame; 447 f1 = viewFrame;
425 f1 = f1 / modelZoomLevel; 448 f1 = f1 / modelZoomLevel;
426 f1 = f1 * modelZoomLevel; 449 f1 = f1 * modelZoomLevel;
427 } 450 }
428 451
429 return (f0 < m_model->getEndFrame()); 452 return (f0 < model->getEndFrame());
430 } 453 }
431 454
432 float 455 float
433 WaveformLayer::getNormalizeGain(LayerGeometryProvider *v, int channel) const 456 WaveformLayer::getNormalizeGain(LayerGeometryProvider *v, int channel) const
434 { 457 {
458 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
459 if (!model) return 0.f;
460
435 sv_frame_t startFrame = v->getStartFrame(); 461 sv_frame_t startFrame = v->getStartFrame();
436 sv_frame_t endFrame = v->getEndFrame(); 462 sv_frame_t endFrame = v->getEndFrame();
437 463
438 sv_frame_t modelStart = m_model->getStartFrame(); 464 sv_frame_t modelStart = model->getStartFrame();
439 sv_frame_t modelEnd = m_model->getEndFrame(); 465 sv_frame_t modelEnd = model->getEndFrame();
440 466
441 sv_frame_t rangeStart, rangeEnd; 467 sv_frame_t rangeStart, rangeEnd;
442 468
443 if (startFrame < modelStart) rangeStart = modelStart; 469 if (startFrame < modelStart) rangeStart = modelStart;
444 else rangeStart = startFrame; 470 else rangeStart = startFrame;
448 else rangeEnd = endFrame; 474 else rangeEnd = endFrame;
449 475
450 if (rangeEnd < rangeStart) rangeEnd = rangeStart; 476 if (rangeEnd < rangeStart) rangeEnd = rangeStart;
451 477
452 RangeSummarisableTimeValueModel::Range range = 478 RangeSummarisableTimeValueModel::Range range =
453 m_model->getSummary(channel, rangeStart, rangeEnd - rangeStart); 479 model->getSummary(channel, rangeStart, rangeEnd - rangeStart);
454 480
455 int minChannel = 0, maxChannel = 0; 481 int minChannel = 0, maxChannel = 0;
456 bool mergingChannels = false, mixingChannels = false; 482 bool mergingChannels = false, mixingChannels = false;
457 483
458 (void)getChannelArrangement(minChannel, maxChannel, 484 (void)getChannelArrangement(minChannel, maxChannel,
459 mergingChannels, mixingChannels); 485 mergingChannels, mixingChannels);
460 486
461 if (mergingChannels || mixingChannels) { 487 if (mergingChannels || mixingChannels) {
462 RangeSummarisableTimeValueModel::Range otherRange = 488 RangeSummarisableTimeValueModel::Range otherRange =
463 m_model->getSummary(1, rangeStart, rangeEnd - rangeStart); 489 model->getSummary(1, rangeStart, rangeEnd - rangeStart);
464 range.setMax(std::max(range.max(), otherRange.max())); 490 range.setMax(std::max(range.max(), otherRange.max()));
465 range.setMin(std::min(range.min(), otherRange.min())); 491 range.setMin(std::min(range.min(), otherRange.min()));
466 range.setAbsmean(std::min(range.absmean(), otherRange.absmean())); 492 range.setAbsmean(std::min(range.absmean(), otherRange.absmean()));
467 } 493 }
468 494
470 } 496 }
471 497
472 void 498 void
473 WaveformLayer::paint(LayerGeometryProvider *v, QPainter &viewPainter, QRect rect) const 499 WaveformLayer::paint(LayerGeometryProvider *v, QPainter &viewPainter, QRect rect) const
474 { 500 {
475 if (!m_model || !m_model->isOK()) { 501 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
502 if (!model || !model->isOK()) {
476 return; 503 return;
477 } 504 }
478 505
479 ZoomLevel zoomLevel = v->getZoomLevel(); 506 ZoomLevel zoomLevel = v->getZoomLevel();
480 507
574 601
575 int desiredBlockSize = 1; 602 int desiredBlockSize = 1;
576 if (zoomLevel.zone == ZoomLevel::FramesPerPixel) { 603 if (zoomLevel.zone == ZoomLevel::FramesPerPixel) {
577 desiredBlockSize = zoomLevel.level; 604 desiredBlockSize = zoomLevel.level;
578 } 605 }
579 int blockSize = m_model->getSummaryBlockSize(desiredBlockSize); 606 int blockSize = model->getSummaryBlockSize(desiredBlockSize);
580 607
581 sv_frame_t frame0; 608 sv_frame_t frame0;
582 sv_frame_t frame1; 609 sv_frame_t frame1;
583 sv_frame_t spare; 610 sv_frame_t spare;
584 611
623 if (m_middleLineHeight != 0.5) { 650 if (m_middleLineHeight != 0.5) {
624 paint->restore(); 651 paint->restore();
625 } 652 }
626 653
627 if (m_aggressive) { 654 if (m_aggressive) {
628 if (m_model->isReady() && rect == v->getPaintRect()) { 655 if (model->isReady() && rect == v->getPaintRect()) {
629 m_cacheValid = true; 656 m_cacheValid = true;
630 m_cacheZoomLevel = zoomLevel; 657 m_cacheZoomLevel = zoomLevel;
631 } 658 }
632 paint->end(); 659 paint->end();
633 delete paint; 660 delete paint;
640 bool mixingOrMerging, 667 bool mixingOrMerging,
641 sv_frame_t frame0, sv_frame_t frame1, 668 sv_frame_t frame0, sv_frame_t frame1,
642 int blockSize, RangeVec &ranges) 669 int blockSize, RangeVec &ranges)
643 const 670 const
644 { 671 {
672 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
673 if (!model) return;
674
645 for (int ch = minChannel; ch <= maxChannel; ++ch) { 675 for (int ch = minChannel; ch <= maxChannel; ++ch) {
646 ranges.push_back({}); 676 ranges.push_back({});
647 m_model->getSummaries(ch, frame0, frame1 - frame0, 677 model->getSummaries(ch, frame0, frame1 - frame0,
648 ranges[ch - minChannel], blockSize); 678 ranges[ch - minChannel], blockSize);
649 #ifdef DEBUG_WAVEFORM_PAINT 679 #ifdef DEBUG_WAVEFORM_PAINT
650 SVCERR << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl; 680 SVCERR << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl;
651 #endif 681 #endif
652 } 682 }
653 683
654 if (mixingOrMerging) { 684 if (mixingOrMerging) {
655 if (minChannel != 0 || maxChannel != 0) { 685 if (minChannel != 0 || maxChannel != 0) {
656 throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); 686 throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels");
657 } else if (m_model->getChannelCount() > 1) { 687 } else if (model->getChannelCount() > 1) {
658 ranges.push_back({}); 688 ranges.push_back({});
659 m_model->getSummaries 689 model->getSummaries
660 (1, frame0, frame1 - frame0, ranges[1], blockSize); 690 (1, frame0, frame1 - frame0, ranges[1], blockSize);
661 } 691 }
662 } 692 }
663 } 693 }
664 694
667 bool mixingOrMerging, 697 bool mixingOrMerging,
668 sv_frame_t frame0, sv_frame_t frame1, 698 sv_frame_t frame0, sv_frame_t frame1,
669 int oversampleBy, RangeVec &ranges) 699 int oversampleBy, RangeVec &ranges)
670 const 700 const
671 { 701 {
702 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
703 if (!model) return;
704
672 if (mixingOrMerging) { 705 if (mixingOrMerging) {
673 if (minChannel != 0 || maxChannel != 0) { 706 if (minChannel != 0 || maxChannel != 0) {
674 throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); 707 throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels");
675 } 708 }
676 if (m_model->getChannelCount() > 1) { 709 if (model->getChannelCount() > 1) {
677 // call back on self for the individual channels with 710 // call back on self for the individual channels with
678 // mixingOrMerging false 711 // mixingOrMerging false
679 getOversampledRanges 712 getOversampledRanges
680 (0, 1, false, frame0, frame1, oversampleBy, ranges); 713 (0, 1, false, frame0, frame1, oversampleBy, ranges);
681 return; 714 return;
684 717
685 // These frame values, tail length, etc variables are at the model 718 // These frame values, tail length, etc variables are at the model
686 // sample rate, not the oversampled rate 719 // sample rate, not the oversampled rate
687 720
688 sv_frame_t tail = 16; 721 sv_frame_t tail = 16;
689 sv_frame_t startFrame = m_model->getStartFrame(); 722 sv_frame_t startFrame = model->getStartFrame();
690 sv_frame_t endFrame = m_model->getEndFrame(); 723 sv_frame_t endFrame = model->getEndFrame();
691 724
692 sv_frame_t rf0 = frame0 - tail; 725 sv_frame_t rf0 = frame0 - tail;
693 if (rf0 < startFrame) { 726 if (rf0 < startFrame) {
694 rf0 = 0; 727 rf0 = 0;
695 } 728 }
704 return; 737 return;
705 } 738 }
706 739
707 for (int ch = minChannel; ch <= maxChannel; ++ch) { 740 for (int ch = minChannel; ch <= maxChannel; ++ch) {
708 floatvec_t oversampled = WaveformOversampler::getOversampledData 741 floatvec_t oversampled = WaveformOversampler::getOversampledData
709 (m_model, ch, frame0, frame1 - frame0, oversampleBy); 742 (*model, ch, frame0, frame1 - frame0, oversampleBy);
710 RangeSummarisableTimeValueModel::RangeBlock rr; 743 RangeSummarisableTimeValueModel::RangeBlock rr;
711 for (float v: oversampled) { 744 for (float v: oversampled) {
712 RangeSummarisableTimeValueModel::Range r; 745 RangeSummarisableTimeValueModel::Range r;
713 r.sample(v); 746 r.sample(v);
714 rr.push_back(r); 747 rr.push_back(r);
736 int blockSize, 769 int blockSize,
737 sv_frame_t frame0, 770 sv_frame_t frame0,
738 sv_frame_t frame1) 771 sv_frame_t frame1)
739 const 772 const
740 { 773 {
774 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
775 if (!model) return;
776
741 int x0 = rect.left(); 777 int x0 = rect.left();
742 int y0 = rect.top(); 778 int y0 = rect.top();
743 779
744 int x1 = rect.right(); 780 int x1 = rect.right();
745 int y1 = rect.bottom(); 781 int y1 = rect.bottom();
757 QColor midColour = baseColour; 793 QColor midColour = baseColour;
758 794
759 if (midColour == Qt::black) { 795 if (midColour == Qt::black) {
760 midColour = Qt::gray; 796 midColour = Qt::gray;
761 } else if (v->hasLightBackground()) { 797 } else if (v->hasLightBackground()) {
762 midColour = midColour.light(150); 798 midColour = midColour.lighter(150);
763 } else { 799 } else {
764 midColour = midColour.light(50); 800 midColour = midColour.lighter(50);
765 } 801 }
766 802
767 double gain = m_effectiveGains[ch]; 803 double gain = m_effectiveGains[ch];
768 804
769 int m = (h / channels) / 2; 805 int m = (h / channels) / 2;
1031 double penWidth = 1.0; 1067 double penWidth = 1.0;
1032 if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) { 1068 if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) {
1033 penWidth = 0.0; 1069 penWidth = 0.0;
1034 } 1070 }
1035 1071
1036 if (m_model->isReady()) { 1072 if (model->isReady()) {
1037 paint->setPen(QPen(baseColour, penWidth)); 1073 paint->setPen(QPen(baseColour, penWidth));
1038 } else { 1074 } else {
1039 paint->setPen(QPen(midColour, penWidth)); 1075 paint->setPen(QPen(midColour, penWidth));
1040 } 1076 }
1041 paint->drawPath(waveformPath); 1077 paint->drawPath(waveformPath);
1134 QString 1170 QString
1135 WaveformLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 1171 WaveformLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
1136 { 1172 {
1137 int x = pos.x(); 1173 int x = pos.x();
1138 1174
1139 if (!m_model || !m_model->isOK()) return ""; 1175 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
1176 if (!model || !model->isOK()) return "";
1140 1177
1141 ZoomLevel zoomLevel = v->getZoomLevel(); 1178 ZoomLevel zoomLevel = v->getZoomLevel();
1142 1179
1143 int desiredBlockSize = 1; 1180 int desiredBlockSize = 1;
1144 if (zoomLevel.zone == ZoomLevel::FramesPerPixel) { 1181 if (zoomLevel.zone == ZoomLevel::FramesPerPixel) {
1145 desiredBlockSize = zoomLevel.level; 1182 desiredBlockSize = zoomLevel.level;
1146 } 1183 }
1147 1184
1148 int blockSize = m_model->getSummaryBlockSize(desiredBlockSize); 1185 int blockSize = model->getSummaryBlockSize(desiredBlockSize);
1149 1186
1150 sv_frame_t f0, f1; 1187 sv_frame_t f0, f1;
1151 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) return ""; 1188 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) return "";
1152 1189
1153 QString text; 1190 QString text;
1154 1191
1155 RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate()); 1192 RealTime rt0 = RealTime::frame2RealTime(f0, model->getSampleRate());
1156 RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate()); 1193 RealTime rt1 = RealTime::frame2RealTime(f1, model->getSampleRate());
1157 1194
1158 if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) { 1195 if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) {
1159 text += tr("Time:\t%1 - %2") 1196 text += tr("Time:\t%1 - %2")
1160 .arg(rt0.toText(true).c_str()) 1197 .arg(rt0.toText(true).c_str())
1161 .arg(rt1.toText(true).c_str()); 1198 .arg(rt1.toText(true).c_str());
1172 if (channels == 0) return ""; 1209 if (channels == 0) return "";
1173 1210
1174 for (int ch = minChannel; ch <= maxChannel; ++ch) { 1211 for (int ch = minChannel; ch <= maxChannel; ++ch) {
1175 1212
1176 RangeSummarisableTimeValueModel::RangeBlock ranges; 1213 RangeSummarisableTimeValueModel::RangeBlock ranges;
1177 m_model->getSummaries(ch, f0, f1 - f0, ranges, blockSize); 1214 model->getSummaries(ch, f0, f1 - f0, ranges, blockSize);
1178 1215
1179 if (ranges.empty()) continue; 1216 if (ranges.empty()) continue;
1180 1217
1181 RangeSummarisableTimeValueModel::Range range = ranges[0]; 1218 RangeSummarisableTimeValueModel::Range range = ranges[0];
1182 1219
1372 } 1409 }
1373 1410
1374 int 1411 int
1375 WaveformLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const 1412 WaveformLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const
1376 { 1413 {
1414 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested
1415 // replacement (horizontalAdvance) was only added in Qt 5.11
1416 // which is too new for us
1417 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1418
1377 if (m_scale == LinearScale) { 1419 if (m_scale == LinearScale) {
1378 return paint.fontMetrics().width("0.0") + 13; 1420 return paint.fontMetrics().width("0.0") + 13;
1379 } else { 1421 } else {
1380 return std::max(paint.fontMetrics().width(tr("0dB")), 1422 return std::max(paint.fontMetrics().width(tr("0dB")),
1381 paint.fontMetrics().width(Strings::minus_infinity)) + 13; 1423 paint.fontMetrics().width(Strings::minus_infinity)) + 13;
1383 } 1425 }
1384 1426
1385 void 1427 void
1386 WaveformLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const 1428 WaveformLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const
1387 { 1429 {
1388 if (!m_model || !m_model->isOK()) { 1430 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
1431 if (!model || !model->isOK()) {
1389 return; 1432 return;
1390 } 1433 }
1391 1434
1392 int channels = 0, minChannel = 0, maxChannel = 0; 1435 int channels = 0, minChannel = 0, maxChannel = 0;
1393 bool mergingChannels = false, mixingChannels = false; 1436 bool mergingChannels = false, mixingChannels = false;