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