Mercurial > hg > svgui
comparison layer/WaveformLayer.cpp @ 1333:59f6830be8d8 zoom
A further refactor with range blocks
author | Chris Cannam |
---|---|
date | Fri, 21 Sep 2018 14:22:53 +0100 |
parents | 6dac67c3ed82 |
children | 0e4551fd7f14 |
comparison
equal
deleted
inserted
replaced
1332:6dac67c3ed82 | 1333:59f6830be8d8 |
---|---|
31 #include <iostream> | 31 #include <iostream> |
32 #include <cmath> | 32 #include <cmath> |
33 | 33 |
34 //#define DEBUG_WAVEFORM_PAINT 1 | 34 //#define DEBUG_WAVEFORM_PAINT 1 |
35 | 35 |
36 | 36 using std::vector; |
37 | 37 |
38 | 38 |
39 WaveformLayer::WaveformLayer() : | 39 WaveformLayer::WaveformLayer() : |
40 SingleColourLayer(), | 40 SingleColourLayer(), |
41 m_model(0), | 41 m_model(0), |
588 | 588 |
589 #ifdef DEBUG_WAVEFORM_PAINT | 589 #ifdef DEBUG_WAVEFORM_PAINT |
590 cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << " and model zoom " << blockSize << ")" << endl; | 590 cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << " and model zoom " << blockSize << ")" << endl; |
591 #endif | 591 #endif |
592 | 592 |
593 RangeSummarisableTimeValueModel::RangeBlock *ranges = | |
594 new RangeSummarisableTimeValueModel::RangeBlock; | |
595 | |
596 RangeSummarisableTimeValueModel::RangeBlock *otherChannelRanges = 0; | |
597 | |
598 while ((int)m_effectiveGains.size() <= maxChannel) { | 593 while ((int)m_effectiveGains.size() <= maxChannel) { |
599 m_effectiveGains.push_back(m_gain); | 594 m_effectiveGains.push_back(m_gain); |
600 } | 595 } |
601 | 596 |
597 vector<RangeSummarisableTimeValueModel::RangeBlock> ranges; | |
598 | |
602 for (int ch = minChannel; ch <= maxChannel; ++ch) { | 599 for (int ch = minChannel; ch <= maxChannel; ++ch) { |
603 | 600 ranges.push_back({}); |
604 m_model->getSummaries(ch, frame0, frame1 - frame0, | 601 m_model->getSummaries(ch, frame0, frame1 - frame0, |
605 *ranges, blockSize); | 602 ranges[ch - minChannel], blockSize); |
606 | |
607 #ifdef DEBUG_WAVEFORM_PAINT | 603 #ifdef DEBUG_WAVEFORM_PAINT |
608 cerr << "channel " << ch << ": " << ranges->size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl; | 604 cerr << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl; |
609 #endif | 605 #endif |
610 | 606 } |
611 if (mergingChannels || mixingChannels) { | 607 |
612 if (m_model->getChannelCount() > 1) { | 608 if (mergingChannels || mixingChannels) { |
613 if (!otherChannelRanges) { | 609 if (minChannel != 0 || maxChannel != 0) { |
614 otherChannelRanges = | 610 SVCERR << "Internal error: min & max channels should be 0 when merging or mixing all channels" << endl; |
615 new RangeSummarisableTimeValueModel::RangeBlock; | 611 } else if (m_model->getChannelCount() > 1) { |
616 } | 612 ranges.push_back({}); |
617 m_model->getSummaries | 613 m_model->getSummaries |
618 (1, frame0, frame1 - frame0, *otherChannelRanges, | 614 (1, frame0, frame1 - frame0, ranges[1], blockSize); |
619 blockSize); | 615 } |
620 } else { | 616 } |
621 if (otherChannelRanges != ranges) delete otherChannelRanges; | 617 |
622 otherChannelRanges = ranges; | 618 for (int ch = minChannel; ch <= maxChannel; ++ch) { |
623 } | 619 paintChannel(v, paint, ch, ranges, |
624 } | |
625 | |
626 paintChannel(v, paint, ch, ranges, otherChannelRanges, | |
627 blockSize, x0, y0, x1, y1, frame0, frame1); | 620 blockSize, x0, y0, x1, y1, frame0, frame1); |
628 } | 621 } |
629 | 622 |
630 if (m_middleLineHeight != 0.5) { | 623 if (m_middleLineHeight != 0.5) { |
631 paint->restore(); | 624 paint->restore(); |
632 } | 625 } |
633 | 626 |
634 if (m_aggressive) { | 627 if (m_aggressive) { |
635 | |
636 if (m_model->isReady() && rect == v->getPaintRect()) { | 628 if (m_model->isReady() && rect == v->getPaintRect()) { |
637 m_cacheValid = true; | 629 m_cacheValid = true; |
638 m_cacheZoomLevel = zoomLevel; | 630 m_cacheZoomLevel = zoomLevel; |
639 } | 631 } |
640 paint->end(); | 632 paint->end(); |
641 delete paint; | 633 delete paint; |
642 viewPainter.drawPixmap(rect, *m_cache, rect); | 634 viewPainter.drawPixmap(rect, *m_cache, rect); |
643 } | 635 } |
644 | |
645 if (otherChannelRanges != ranges) delete otherChannelRanges; | |
646 delete ranges; | |
647 } | 636 } |
648 | 637 |
649 void | 638 void |
650 WaveformLayer::paintChannel(LayerGeometryProvider *v, QPainter *paint, int ch, | 639 WaveformLayer::paintChannel(LayerGeometryProvider *v, QPainter *paint, int ch, |
651 const RangeSummarisableTimeValueModel::RangeBlock *ranges, | 640 const vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges, |
652 const RangeSummarisableTimeValueModel::RangeBlock *otherChannelRanges, | |
653 int blockSize, int x0, int y0, int x1, int y1, | 641 int blockSize, int x0, int y0, int x1, int y1, |
654 sv_frame_t frame0, sv_frame_t frame1) | 642 sv_frame_t frame0, sv_frame_t frame1) |
655 const | 643 const |
656 { | 644 { |
657 int w = v->getPaintWidth(); | 645 int w = v->getPaintWidth(); |
663 channels = getChannelArrangement(minChannel, maxChannel, | 651 channels = getChannelArrangement(minChannel, maxChannel, |
664 mergingChannels, mixingChannels); | 652 mergingChannels, mixingChannels); |
665 if (channels == 0) return; | 653 if (channels == 0) return; |
666 | 654 |
667 QColor baseColour = getBaseQColor(); | 655 QColor baseColour = getBaseQColor(); |
668 std::vector<QColor> greys = getPartialShades(v); | 656 vector<QColor> greys = getPartialShades(v); |
669 | 657 |
670 QColor midColour = baseColour; | 658 QColor midColour = baseColour; |
671 if (midColour == Qt::black) { | 659 if (midColour == Qt::black) { |
672 midColour = Qt::gray; | 660 midColour = Qt::gray; |
673 } else if (v->hasLightBackground()) { | 661 } else if (v->hasLightBackground()) { |
751 paint->drawLine(x0, ny, x1, ny); | 739 paint->drawLine(x0, ny, x1, ny); |
752 } | 740 } |
753 } | 741 } |
754 } | 742 } |
755 | 743 |
744 int rangeix = ch - minChannel; | |
745 | |
756 for (int x = x0; x <= x1; ++x) { | 746 for (int x = x0; x <= x1; ++x) { |
757 | |
758 RangeSummarisableTimeValueModel::Range range; | |
759 | 747 |
760 sv_frame_t f0, f1; | 748 sv_frame_t f0, f1; |
761 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) continue; | 749 if (!getSourceFramesForX(v, x, blockSize, f0, f1)) continue; |
762 f1 = f1 - 1; | 750 f1 = f1 - 1; |
763 | 751 |
775 | 763 |
776 if (i1 > i0 + 1) { | 764 if (i1 > i0 + 1) { |
777 cerr << "WaveformLayer::paint: ERROR: i1 " << i1 << " > i0 " << i0 << " plus one (zoom = " << v->getZoomLevel() << ", model zoom = " << blockSize << ")" << endl; | 765 cerr << "WaveformLayer::paint: ERROR: i1 " << i1 << " > i0 " << i0 << " plus one (zoom = " << v->getZoomLevel() << ", model zoom = " << blockSize << ")" << endl; |
778 } | 766 } |
779 | 767 |
780 if (ranges && i0 < (sv_frame_t)ranges->size()) { | 768 const auto &r = ranges[rangeix]; |
781 | 769 RangeSummarisableTimeValueModel::Range range; |
782 range = (*ranges)[size_t(i0)]; | 770 |
783 | 771 if (in_range_for(r, i0)) { |
784 if (i1 > i0 && i1 < (int)ranges->size()) { | 772 |
785 range.setMax(std::max(range.max(), | 773 range = r[i0]; |
786 (*ranges)[size_t(i1)].max())); | 774 |
787 range.setMin(std::min(range.min(), | 775 if (i1 > i0 && in_range_for(r, i1)) { |
788 (*ranges)[size_t(i1)].min())); | 776 range.setMax(std::max(range.max(), r[i1].max())); |
789 range.setAbsmean((range.absmean() | 777 range.setMin(std::min(range.min(), r[i1].min())); |
790 + (*ranges)[size_t(i1)].absmean()) / 2); | 778 range.setAbsmean((range.absmean() + r[i1].absmean()) / 2); |
791 } | 779 } |
792 | 780 |
793 } else { | 781 } else { |
794 #ifdef DEBUG_WAVEFORM_PAINT | 782 #ifdef DEBUG_WAVEFORM_PAINT |
795 cerr << "No (or not enough) ranges for i0 = " << i0 << endl; | 783 cerr << "No (or not enough) ranges for i0 = " << i0 << endl; |
797 continue; | 785 continue; |
798 } | 786 } |
799 | 787 |
800 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0; | 788 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0; |
801 | 789 |
802 if (mergingChannels) { | 790 if (mergingChannels && ranges.size() > 1) { |
803 | 791 |
804 if (otherChannelRanges && i0 < (sv_frame_t)otherChannelRanges->size()) { | 792 const auto &other = ranges[1]; |
793 | |
794 if (in_range_for(other, i0)) { | |
805 | 795 |
806 range.setMax(fabsf(range.max())); | 796 range.setMax(fabsf(range.max())); |
807 range.setMin(-fabsf((*otherChannelRanges)[size_t(i0)].max())); | 797 range.setMin(-fabsf(other[i0].max())); |
808 range.setAbsmean | 798 range.setAbsmean |
809 ((range.absmean() + | 799 ((range.absmean() + other[i0].absmean()) / 2); |
810 (*otherChannelRanges)[size_t(i0)].absmean()) / 2); | 800 |
811 | 801 if (i1 > i0 && in_range_for(other, i1)) { |
812 if (i1 > i0 && i1 < (sv_frame_t)otherChannelRanges->size()) { | |
813 // let's not concern ourselves about the mean | 802 // let's not concern ourselves about the mean |
814 range.setMin | 803 range.setMin(std::min(range.min(), |
815 (std::min | 804 -fabsf(other[i1].max()))); |
816 (range.min(), | |
817 -fabsf((*otherChannelRanges)[size_t(i1)].max()))); | |
818 } | 805 } |
819 } | 806 } |
820 | 807 |
821 } else if (mixingChannels) { | 808 } else if (mixingChannels && ranges.size() > 1) { |
822 | 809 |
823 if (otherChannelRanges && i0 < (sv_frame_t)otherChannelRanges->size()) { | 810 const auto &other = ranges[1]; |
824 | 811 |
825 range.setMax((range.max() | 812 if (in_range_for(other, i0)) { |
826 + (*otherChannelRanges)[size_t(i0)].max()) / 2); | 813 |
827 range.setMin((range.min() | 814 range.setMax((range.max() + other[i0].max()) / 2); |
828 + (*otherChannelRanges)[size_t(i0)].min()) / 2); | 815 range.setMin((range.min() + other[i0].min()) / 2); |
829 range.setAbsmean((range.absmean() | 816 range.setAbsmean((range.absmean() + other[i0].absmean()) / 2); |
830 + (*otherChannelRanges)[size_t(i0)].absmean()) / 2); | |
831 } | 817 } |
832 } | 818 } |
833 | 819 |
834 int greyLevels = 1; | 820 int greyLevels = 1; |
835 if (m_greyscale && (m_scale == LinearScale)) greyLevels = 4; | 821 if (m_greyscale && (m_scale == LinearScale)) greyLevels = 4; |