comparison layer/WaveformLayer.cpp @ 1338:6d091348e4e9 zoom

Get oversampled rendering almost working, but I think we need to take more care with the oversampling itself
author Chris Cannam
date Tue, 25 Sep 2018 16:38:50 +0100
parents 4f9a3c84be60
children b0555b434575
comparison
equal deleted inserted replaced
1337:4f9a3c84be60 1338:6d091348e4e9
31 #include <iostream> 31 #include <iostream>
32 #include <cmath> 32 #include <cmath>
33 33
34 #include <bqresample/Resampler.h> 34 #include <bqresample/Resampler.h>
35 35
36 //#define DEBUG_WAVEFORM_PAINT 1 36 #define DEBUG_WAVEFORM_PAINT 1
37 //#define DEBUG_WAVEFORM_PAINT_BY_PIXEL 1
37 38
38 using std::vector; 39 using std::vector;
39 40
40 41
41 WaveformLayer::WaveformLayer() : 42 WaveformLayer::WaveformLayer() :
48 m_channelMode(SeparateChannels), 49 m_channelMode(SeparateChannels),
49 m_channel(-1), 50 m_channel(-1),
50 m_scale(LinearScale), 51 m_scale(LinearScale),
51 m_middleLineHeight(0.5), 52 m_middleLineHeight(0.5),
52 m_aggressive(false), 53 m_aggressive(false),
53 m_oversampleRate(8),
54 m_oversampleTail(200),
55 m_oversampler(0), 54 m_oversampler(0),
56 m_cache(0), 55 m_cache(0),
57 m_cacheValid(false) 56 m_cacheValid(false)
58 { 57 {
59 } 58 }
86 if (!m_model || !m_model->isOK()) return; 85 if (!m_model || !m_model->isOK()) return;
87 86
88 delete m_oversampler; 87 delete m_oversampler;
89 breakfastquay::Resampler::Parameters params; 88 breakfastquay::Resampler::Parameters params;
90 params.initialSampleRate = m_model->getSampleRate(); 89 params.initialSampleRate = m_model->getSampleRate();
91 m_oversampler = new breakfastquay::Resampler 90 // Oversampler is initialised with 1 channel: we resample the
92 (params, m_model->getChannelCount()); 91 // channels individually for practical reasons (because channel
92 // configuration may vary)
93 m_oversampler = new breakfastquay::Resampler(params, 1);
93 94
94 connectSignals(m_model); 95 connectSignals(m_model);
95 96
96 emit modelReplaced(); 97 emit modelReplaced();
97 98
431 f1 = 0; 432 f1 = 0;
432 return false; 433 return false;
433 } 434 }
434 435
435 f0 = viewFrame; 436 f0 = viewFrame;
436
437 f0 = f0 / modelZoomLevel; 437 f0 = f0 / modelZoomLevel;
438 f0 = f0 * modelZoomLevel; 438 f0 = f0 * modelZoomLevel;
439 439
440 viewFrame = v->getFrameForX(x + 1); 440 viewFrame = v->getFrameForX(x + 1);
441 441
495 495
496 ZoomLevel zoomLevel = v->getZoomLevel(); 496 ZoomLevel zoomLevel = v->getZoomLevel();
497 497
498 #ifdef DEBUG_WAVEFORM_PAINT 498 #ifdef DEBUG_WAVEFORM_PAINT
499 Profiler profiler("WaveformLayer::paint", true); 499 Profiler profiler("WaveformLayer::paint", true);
500 cerr << "WaveformLayer::paint (" << rect.x() << "," << rect.y() 500 SVCERR << "WaveformLayer::paint (" << rect.x() << "," << rect.y()
501 << ") [" << rect.width() << "x" << rect.height() << "]: zoom " << zoomLevel << endl; 501 << ") [" << rect.width() << "x" << rect.height() << "]: zoom " << zoomLevel << endl;
502 #endif 502 #endif
503 503
504 int channels = 0, minChannel = 0, maxChannel = 0; 504 int channels = 0, minChannel = 0, maxChannel = 0;
505 bool mergingChannels = false, mixingChannels = false; 505 bool mergingChannels = false, mixingChannels = false;
514 QPainter *paint; 514 QPainter *paint;
515 515
516 if (m_aggressive) { 516 if (m_aggressive) {
517 517
518 #ifdef DEBUG_WAVEFORM_PAINT 518 #ifdef DEBUG_WAVEFORM_PAINT
519 cerr << "WaveformLayer::paint: aggressive is true" << endl; 519 SVCERR << "WaveformLayer::paint: aggressive is true" << endl;
520 #endif 520 #endif
521 521
522 using namespace std::rel_ops; 522 using namespace std::rel_ops;
523 523
524 if (m_cacheValid && (zoomLevel != m_cacheZoomLevel)) { 524 if (m_cacheValid && (zoomLevel != m_cacheZoomLevel)) {
526 } 526 }
527 527
528 if (!m_cache || m_cache->width() != w || m_cache->height() != h) { 528 if (!m_cache || m_cache->width() != w || m_cache->height() != h) {
529 #ifdef DEBUG_WAVEFORM_PAINT 529 #ifdef DEBUG_WAVEFORM_PAINT
530 if (m_cache) { 530 if (m_cache) {
531 cerr << "WaveformLayer::paint: cache size " << m_cache->width() << "x" << m_cache->height() << " differs from view size " << w << "x" << h << ": regenerating aggressive cache" << endl; 531 SVCERR << "WaveformLayer::paint: cache size " << m_cache->width() << "x" << m_cache->height() << " differs from view size " << w << "x" << h << ": regenerating aggressive cache" << endl;
532 } 532 }
533 #endif 533 #endif
534 delete m_cache; 534 delete m_cache;
535 m_cache = new QPixmap(w, h); 535 m_cache = new QPixmap(w, h);
536 m_cacheValid = false; 536 m_cacheValid = false;
601 601
602 getSourceFramesForX(v, x0, blockSize, frame0, spare); 602 getSourceFramesForX(v, x0, blockSize, frame0, spare);
603 getSourceFramesForX(v, x1, blockSize, spare, frame1); 603 getSourceFramesForX(v, x1, blockSize, spare, frame1);
604 604
605 #ifdef DEBUG_WAVEFORM_PAINT 605 #ifdef DEBUG_WAVEFORM_PAINT
606 cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << " and model zoom " << blockSize << ")" << endl; 606 SVCERR << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << " and model zoom " << blockSize << ")" << endl;
607 #endif 607 #endif
608 608
609 m_effectiveGains.clear();
609 while ((int)m_effectiveGains.size() <= maxChannel) { 610 while ((int)m_effectiveGains.size() <= maxChannel) {
610 m_effectiveGains.push_back(m_gain); 611 m_effectiveGains.push_back(m_gain);
611 } 612 }
612 if (m_autoNormalize) { 613 if (m_autoNormalize) {
613 for (int ch = minChannel; ch <= maxChannel; ++ch) { 614 for (int ch = minChannel; ch <= maxChannel; ++ch) {
614 m_effectiveGains[ch] = getNormalizeGain(v, ch); 615 m_effectiveGains[ch] = getNormalizeGain(v, ch);
615 } 616 }
616 } 617 }
617 618
619 RangeVec ranges;
620
618 if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) { 621 if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) {
619 622 getSummaryRanges(minChannel, maxChannel,
620 vector<RangeSummarisableTimeValueModel::RangeBlock> ranges; 623 mixingChannels || mergingChannels,
621 624 frame0, frame1,
622 for (int ch = minChannel; ch <= maxChannel; ++ch) { 625 blockSize, ranges);
623 ranges.push_back({});
624 m_model->getSummaries(ch, frame0, frame1 - frame0,
625 ranges[ch - minChannel], blockSize);
626 #ifdef DEBUG_WAVEFORM_PAINT
627 cerr << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl;
628 #endif
629 }
630
631 if (mergingChannels || mixingChannels) {
632 if (minChannel != 0 || maxChannel != 0) {
633 SVCERR << "Internal error: min & max channels should be 0 when merging or mixing all channels" << endl;
634 } else if (m_model->getChannelCount() > 1) {
635 ranges.push_back({});
636 m_model->getSummaries
637 (1, frame0, frame1 - frame0, ranges[1], blockSize);
638 }
639 }
640
641 for (int ch = minChannel; ch <= maxChannel; ++ch) {
642 paintChannelSummarised(v, paint, rect, ch,
643 ranges, blockSize, frame0, frame1);
644 }
645 } else { 626 } else {
646 627 getOversampledRanges(minChannel, maxChannel,
647 for (int ch = minChannel; ch <= maxChannel; ++ch) { 628 mixingChannels || mergingChannels,
648 paintChannelOversampled(v, paint, rect, ch, frame0, frame1); 629 frame0, frame1,
649 } 630 v->getZoomLevel().level, ranges);
631 }
632
633 for (int ch = minChannel; ch <= maxChannel; ++ch) {
634 paintChannel(v, paint, rect, ch, ranges, blockSize, frame0, frame1);
650 } 635 }
651 636
652 if (m_middleLineHeight != 0.5) { 637 if (m_middleLineHeight != 0.5) {
653 paint->restore(); 638 paint->restore();
654 } 639 }
663 viewPainter.drawPixmap(rect, *m_cache, rect); 648 viewPainter.drawPixmap(rect, *m_cache, rect);
664 } 649 }
665 } 650 }
666 651
667 void 652 void
668 WaveformLayer::paintChannelSummarised(LayerGeometryProvider *v, 653 WaveformLayer::getSummaryRanges(int minChannel, int maxChannel,
669 QPainter *paint, 654 bool mixingOrMerging,
670 QRect rect, int ch, 655 sv_frame_t frame0, sv_frame_t frame1,
671 const vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges, 656 int blockSize, RangeVec &ranges)
672 int blockSize, 657 const
673 sv_frame_t frame0, sv_frame_t frame1) 658 {
659 for (int ch = minChannel; ch <= maxChannel; ++ch) {
660 ranges.push_back({});
661 m_model->getSummaries(ch, frame0, frame1 - frame0,
662 ranges[ch - minChannel], blockSize);
663 #ifdef DEBUG_WAVEFORM_PAINT
664 SVCERR << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl;
665 #endif
666 }
667
668 if (mixingOrMerging) {
669 if (minChannel != 0 || maxChannel != 0) {
670 SVCERR << "Internal error: min & max channels should be 0 when merging or mixing all channels" << endl;
671 } else if (m_model->getChannelCount() > 1) {
672 ranges.push_back({});
673 m_model->getSummaries
674 (1, frame0, frame1 - frame0, ranges[1], blockSize);
675 }
676 }
677 }
678
679 void
680 WaveformLayer::getOversampledRanges(int minChannel, int maxChannel,
681 bool mixingOrMerging,
682 sv_frame_t frame0, sv_frame_t frame1,
683 int oversampleBy, RangeVec &ranges)
684 const
685 {
686 // These frame values, tail length, etc variables are at the model
687 // sample rate, not the oversampled rate
688
689 sv_frame_t tail = 16;
690 sv_frame_t leftTail = tail, rightTail = tail;
691 sv_frame_t startFrame = m_model->getStartFrame();
692 sv_frame_t endFrame = m_model->getEndFrame();
693
694 sv_frame_t rf0 = frame0 - tail;
695 if (rf0 < startFrame) {
696 leftTail = frame0 - startFrame;
697 rf0 = 0;
698 }
699
700 sv_frame_t rf1 = frame1 + tail;
701 if (rf1 >= endFrame) {
702 rightTail = endFrame - 1 - frame1;
703 rf1 = endFrame - 1;
704 }
705 if (rf1 <= rf0) {
706 SVCERR << "WARNING: getOversampledRanges: rf1 (" << rf1 << ") <= rf0 ("
707 << rf0 << ")" << endl;
708 return;
709 }
710
711 for (int ch = minChannel; ch <= maxChannel; ++ch) {
712 floatvec_t raw = m_model->getData(ch, rf0, rf1 - rf0);
713 floatvec_t oversampled(oversampleBy * (frame1 - frame0 + 2 * tail),
714 0.f);
715 //!!! return value, err etc
716 m_oversampler->reset();
717 m_oversampler->resampleInterleaved(oversampled.data(),
718 oversampled.size(),
719 raw.data(),
720 raw.size(),
721 oversampleBy,
722 true);
723 RangeSummarisableTimeValueModel::RangeBlock rr;
724 for (sv_frame_t ix = leftTail * oversampleBy;
725 in_range_for(oversampled, ix + (rightTail * oversampleBy));
726 ++ix) {
727 RangeSummarisableTimeValueModel::Range r;
728 r.sample(oversampled[ix]);
729 rr.push_back(r);
730 }
731 ranges.push_back(rr);
732
733 #ifdef DEBUG_WAVEFORM_PAINT
734 SVCERR << "getOversampledRanges: " << frame0 << " -> " << frame1
735 << " (" << frame1 - frame0 << "-frame range) at ratio "
736 << oversampleBy << " with tail " << tail
737 << " -> got " << oversampled.size()
738 << " oversampled values for channel " << ch
739 << ", from which returning " << rr.size() << " ranges" << endl;
740 #endif
741 }
742
743 //!!! + channel modes
744
745 return;
746 }
747
748 void
749 WaveformLayer::paintChannel(LayerGeometryProvider *v,
750 QPainter *paint,
751 QRect rect, int ch,
752 const RangeVec &ranges,
753 int blockSize,
754 sv_frame_t frame0, sv_frame_t frame1)
674 const 755 const
675 { 756 {
676 int x0 = rect.left(); 757 int x0 = rect.left();
677 int y0 = rect.top(); 758 int y0 = rect.top();
678 759
707 788
708 int m = (h / channels) / 2; 789 int m = (h / channels) / 2;
709 int my = m + (((ch - minChannel) * h) / channels); 790 int my = m + (((ch - minChannel) * h) / channels);
710 791
711 #ifdef DEBUG_WAVEFORM_PAINT 792 #ifdef DEBUG_WAVEFORM_PAINT
712 cerr << "ch = " << ch << ", channels = " << channels << ", m = " << m << ", my = " << my << ", h = " << h << endl; 793 SVCERR << "ch = " << ch << ", channels = " << channels << ", m = " << m << ", my = " << my << ", h = " << h << endl;
713 #endif 794 #endif
714 795
715 if (my - m > y1 || my + m < y0) return; 796 if (my - m > y1 || my + m < y0) return;
716 797
717 if ((m_scale == dBScale || m_scale == MeterScale) && 798 if ((m_scale == dBScale || m_scale == MeterScale) &&
724 paint->drawLine(x0, my, x1, my); 805 paint->drawLine(x0, my, x1, my);
725 806
726 paintChannelScaleGuides(v, paint, rect, ch); 807 paintChannelScaleGuides(v, paint, rect, ch);
727 808
728 int rangeix = ch - minChannel; 809 int rangeix = ch - minChannel;
810
811 #ifdef DEBUG_WAVEFORM_PAINT
812 SVCERR << "paint channel " << ch << ": frame0 = " << frame0 << ", frame1 = " << frame1 << ", blockSize = " << blockSize << ", have " << ranges.size() << " range blocks of which ours is index " << rangeix << " with " << ranges[rangeix].size() << " ranges in it" << endl;
813 #endif
814
815 for (int x = x0; x <= x1; ++x) {
816
817 sv_frame_t f0, f1;
818 sv_frame_t i0, i1;
819
820 bool showIndividualSample = false;
729 821
730 for (int x = x0; x <= x1; ++x) { 822 if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) {
731 823 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) {
732 sv_frame_t f0, f1; 824 continue;
733 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) continue; 825 }
734 f1 = f1 - 1; 826 f1 = f1 - 1;
827 i0 = (f0 - frame0) / blockSize;
828 i1 = (f1 - frame0) / blockSize;
829 } else {
830 int oversampleBy = v->getZoomLevel().level;
831 f0 = f1 = v->getFrameForX(x);
832 int xf0 = v->getXForFrame(f0);
833 showIndividualSample = (x == xf0);
834 i0 = i1 = (f0 - frame0) * oversampleBy + (x - xf0);
835 }
735 836
736 if (f0 < frame0) { 837 if (f0 < frame0) {
737 cerr << "ERROR: WaveformLayer::paint: pixel " << x << " has f0 = " << f0 << " which is less than range frame0 " << frame0 << " for x0 = " << x0 << endl; 838 SVCERR << "ERROR: WaveformLayer::paint: pixel " << x << " has f0 = " << f0 << " which is less than range frame0 " << frame0 << " for x0 = " << x0 << endl;
738 continue; 839 continue;
739 } 840 }
740 841
741 sv_frame_t i0 = (f0 - frame0) / blockSize; 842 #ifdef DEBUG_WAVEFORM_PAINT_BY_PIXEL
742 sv_frame_t i1 = (f1 - frame0) / blockSize; 843 SVCERR << "WaveformLayer::paint: pixel " << x << ": i0 " << i0 << " (f " << f0 << "), i1 " << i1 << " (f " << f1 << ")" << endl;
743
744 #ifdef DEBUG_WAVEFORM_PAINT
745 cerr << "WaveformLayer::paint: pixel " << x << ": i0 " << i0 << " (f " << f0 << "), i1 " << i1 << " (f " << f1 << ")" << endl;
746 #endif 844 #endif
747 845
748 if (i1 > i0 + 1) { 846 if (i1 > i0 + 1) {
749 cerr << "WaveformLayer::paint: ERROR: i1 " << i1 << " > i0 " << i0 << " plus one (zoom = " << v->getZoomLevel() << ", model zoom = " << blockSize << ")" << endl; 847 SVCERR << "WaveformLayer::paint: ERROR: i1 " << i1 << " > i0 " << i0 << " plus one (zoom = " << v->getZoomLevel() << ", model zoom = " << blockSize << ")" << endl;
750 } 848 }
751 849
752 const auto &r = ranges[rangeix]; 850 const auto &r = ranges[rangeix];
753 RangeSummarisableTimeValueModel::Range range; 851 RangeSummarisableTimeValueModel::Range range;
754 852
762 range.setAbsmean((range.absmean() + r[i1].absmean()) / 2); 860 range.setAbsmean((range.absmean() + r[i1].absmean()) / 2);
763 } 861 }
764 862
765 } else { 863 } else {
766 #ifdef DEBUG_WAVEFORM_PAINT 864 #ifdef DEBUG_WAVEFORM_PAINT
767 cerr << "No (or not enough) ranges for i0 = " << i0 << endl; 865 SVCERR << "No (or not enough) ranges for index i0 = " << i0 << " (there are " << r.size() << " range(s))" << endl;
768 #endif 866 #endif
769 continue; 867 continue;
770 } 868 }
771 869
772 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0; 870 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0;
882 if (meanBottom == rangeBottom && m_scale == LinearScale) { 980 if (meanBottom == rangeBottom && m_scale == LinearScale) {
883 if (meanBottom > meanTop) --meanBottom; 981 if (meanBottom > meanTop) --meanBottom;
884 else drawMean = false; 982 else drawMean = false;
885 } 983 }
886 984
985 if (showIndividualSample) {
986 paint->setPen(baseColour);
987 paint->drawRect(x-1, rangeTop-1, 3, 3);
988 }
989
887 if (x != x0 && prevRangeBottom != -1) { 990 if (x != x0 && prevRangeBottom != -1) {
888 if (prevRangeBottom > rangeBottom + 1 && 991 if (prevRangeBottom > rangeBottom + 1 &&
889 prevRangeTop > rangeBottom + 1) { 992 prevRangeTop > rangeBottom + 1) {
890 // paint->setPen(midColour); 993 // paint->setPen(midColour);
891 paint->setPen(baseColour); 994 paint->setPen(baseColour);
912 } 1015 }
913 } else { 1016 } else {
914 paint->setPen(midColour); 1017 paint->setPen(midColour);
915 } 1018 }
916 1019
917 #ifdef DEBUG_WAVEFORM_PAINT 1020 #ifdef DEBUG_WAVEFORM_PAINT_BY_PIXEL
918 cerr << "range " << rangeBottom << " -> " << rangeTop << ", means " << meanBottom << " -> " << meanTop << ", raw range " << range.min() << " -> " << range.max() << endl; 1021 SVCERR << "range " << rangeBottom << " -> " << rangeTop << ", means " << meanBottom << " -> " << meanTop << ", raw range " << range.min() << " -> " << range.max() << endl;
919 #endif 1022 #endif
920 1023
921 if (rangeTop == rangeBottom) { 1024 if (rangeTop == rangeBottom) {
922 paint->drawPoint(x, rangeTop); 1025 paint->drawPoint(x, rangeTop);
923 } else { 1026 } else {
955 prevRangeTop = rangeTop; 1058 prevRangeTop = rangeTop;
956 } 1059 }
957 } 1060 }
958 1061
959 void 1062 void
960 WaveformLayer::paintChannelOversampled(LayerGeometryProvider *v,
961 QPainter *paint,
962 QRect rect,
963 int ch,
964 sv_frame_t frame0, sv_frame_t frame1)
965 const
966 {
967 int x0 = rect.left();
968 int y0 = rect.top();
969
970 int x1 = rect.right();
971 int y1 = rect.bottom();
972
973 int h = v->getPaintHeight();
974
975 int channels = 0, minChannel = 0, maxChannel = 0;
976 bool mergingChannels = false, mixingChannels = false;
977
978 channels = getChannelArrangement(minChannel, maxChannel,
979 mergingChannels, mixingChannels);
980 if (channels == 0) return;
981
982 QColor baseColour = getBaseQColor();
983 vector<QColor> greys = getPartialShades(v);
984
985 QColor midColour = baseColour;
986 if (midColour == Qt::black) {
987 midColour = Qt::gray;
988 } else if (v->hasLightBackground()) {
989 midColour = midColour.light(150);
990 } else {
991 midColour = midColour.light(50);
992 }
993
994 double gain = m_effectiveGains[ch];
995
996 int m = (h / channels) / 2;
997 int my = m + (((ch - minChannel) * h) / channels);
998
999 #ifdef DEBUG_WAVEFORM_PAINT
1000 cerr << "ch = " << ch << ", channels = " << channels << ", m = " << m << ", my = " << my << ", h = " << h << endl;
1001 #endif
1002
1003 if (my - m > y1 || my + m < y0) return;
1004
1005 if ((m_scale == dBScale || m_scale == MeterScale) &&
1006 m_channelMode != MergeChannels) {
1007 m = (h / channels);
1008 my = m + (((ch - minChannel) * h) / channels);
1009 }
1010
1011 paint->setPen(greys[1]);
1012 paint->drawLine(x0, my, x1, my);
1013
1014 paintChannelScaleGuides(v, paint, rect, ch);
1015
1016 for (sv_frame_t f = frame0; f <= frame1; ++f) {
1017
1018 }
1019 }
1020
1021 void
1022 WaveformLayer::paintChannelScaleGuides(LayerGeometryProvider *v, 1063 WaveformLayer::paintChannelScaleGuides(LayerGeometryProvider *v,
1023 QPainter *paint, 1064 QPainter *paint,
1024 QRect rect, 1065 QRect rect,
1025 int ch) const 1066 int ch) const
1026 { 1067 {
1204 case dBScale: 1245 case dBScale:
1205 vy = dBscale(value, m); 1246 vy = dBscale(value, m);
1206 break; 1247 break;
1207 } 1248 }
1208 1249
1209 // cerr << "mergingChannels= " << mergingChannels << ", channel = " << channel << ", value = " << value << ", vy = " << vy << endl; 1250 // SVCERR << "mergingChannels= " << mergingChannels << ", channel = " << channel << ", value = " << value << ", vy = " << vy << endl;
1210 1251
1211 return my - vy; 1252 return my - vy;
1212 } 1253 }
1213 1254
1214 double 1255 double