Mercurial > hg > svgui
changeset 1542:10fe8124dc17
Overhaul the way WaveformLayer reports value and display extents. The previous logic has been nonsense for a very long time, excused only by the fact that it was very seldom relevant (only really if another layer with unit V came along that wanted to auto-align with it). Partial fix for #1954 Peculiar alignment for Amplitude Follower y-scale in Auto-Align mode
author | Chris Cannam |
---|---|
date | Wed, 16 Oct 2019 12:23:36 +0100 |
parents | b4b5b8dd5fe1 |
children | 35c7b7a592f0 |
files | layer/WaveformLayer.cpp layer/WaveformLayer.h |
diffstat | 2 files changed, 69 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/WaveformLayer.cpp Wed Oct 16 12:19:04 2019 +0100 +++ b/layer/WaveformLayer.cpp Wed Oct 16 12:23:36 2019 +0100 @@ -38,6 +38,8 @@ using std::vector; +double +WaveformLayer::m_dBMin = -50.0; WaveformLayer::WaveformLayer() : SingleColourLayer(), @@ -46,6 +48,7 @@ m_showMeans(true), m_channelMode(SeparateChannels), m_channel(-1), + m_channelCount(0), m_scale(LinearScale), m_middleLineHeight(0.5), m_aggressive(false), @@ -76,10 +79,12 @@ if (!modelId.isNone() && !newModel) { throw std::logic_error("Not a RangeSummarisableTimeValueModel"); } - + if (m_model == modelId) return; m_model = modelId; + // NB newModel may legitimately be null + m_cacheValid = false; bool channelsChanged = false; @@ -97,6 +102,7 @@ } if (newModel) { + m_channelCount = newModel->getChannelCount(); connectSignals(m_model); } @@ -112,9 +118,7 @@ list.push_back("Scale"); list.push_back("Gain"); list.push_back("Normalize Visible Area"); - - auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model); - if (model && model->getChannelCount() > 1 && m_channel == -1) { + if (m_channelCount > 1 && m_channel == -1) { list.push_back("Channels"); } @@ -349,20 +353,57 @@ bool WaveformLayer::getValueExtents(double &min, double &max, - bool &, QString &unit) const + bool &log, QString &unit) const { + unit = "V"; + + // There is no point in returning extents here unless we have a + // scale that anyone else can actually calculate with, which is + // only the case if getDisplayExtents is returning successfully + + if (getDisplayExtents(min, max)) { + log = (m_scale == dBScale); + return true; + } else { + return false; + } +} + +bool +WaveformLayer::getDisplayExtents(double &min, double &max) const +{ + // If we have a single channel visible and either linear or log + // (dB) scale, then we have a continuous scale that runs from -1 + // to 1 or -dBMin to 0 and we can offer it as an alignment target + // for other layers with the same unit. We can also do this in + // butterfly mode, but only with linear scale. Otherwise no. + + if (m_scale == MeterScale) { + return false; + } + + if (m_channelCount > 1) { + if (m_channelMode == SeparateChannels) { + return false; + } + if (m_channelMode == MergeChannels && m_scale != LinearScale) { + return false; + } + } + if (m_scale == LinearScale) { - min = 0.0; max = 1.0; - unit = "V"; - } else if (m_scale == MeterScale) { - return false; //!!! - } else { - min = AudioLevel::multiplier_to_dB(0.0); - max = AudioLevel::multiplier_to_dB(1.0); - unit = "dB"; + min = -1.0; + return true; } - return true; + + if (m_scale == dBScale) { + max = 1.0; + min = AudioLevel::dB_to_multiplier(m_dBMin); + return true; + } + + return false; } double @@ -370,9 +411,9 @@ { if (sample < 0.0) return dBscale(-sample, m); double dB = AudioLevel::multiplier_to_dB(sample); - if (dB < -50.0) return 0; + if (dB < m_dBMin) return 0; if (dB > 0.0) return m; - return ((dB + 50.0) * m) / 50.0; + return ((dB - m_dBMin) * m) / (-m_dBMin); } int @@ -380,10 +421,7 @@ bool &merging, bool &mixing) const { - auto model = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model); - if (!model || !model->isOK()) return 0; - - int channels = model->getChannelCount(); + int channels = m_channelCount; if (channels == 0) return 0; int rawChannels = channels; @@ -495,7 +533,7 @@ mergingChannels, mixingChannels); if (mergingChannels || mixingChannels) { - if (model->getChannelCount() > 1) { + if (m_channelCount > 1) { RangeSummarisableTimeValueModel::Range otherRange = model->getSummary(1, rangeStart, rangeEnd - rangeStart); range.setMax(std::max(range.max(), otherRange.max())); @@ -696,7 +734,7 @@ if (mixingOrMerging) { if (minChannel != 0 || maxChannel != 0) { throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); - } else if (model->getChannelCount() > 1) { + } else if (m_channelCount > 1) { ranges.push_back({}); model->getSummaries (1, frame0, frame1 - frame0, ranges[1], blockSize); @@ -720,7 +758,7 @@ if (minChannel != 0 || maxChannel != 0) { throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); } - if (model->getChannelCount() > 1) { + if (m_channelCount > 1) { // call back on self for the individual channels with // mixingOrMerging false getOversampledRanges @@ -1343,7 +1381,7 @@ int vy = my - y; double value = 0; - double thresh = -50.f; + double thresh = m_dBMin; switch (m_scale) { @@ -1374,7 +1412,7 @@ if (m_scale == dBScale || m_scale == MeterScale) { - double thresh = -50.f; + double thresh = m_dBMin; if (value > 0.0) { value = 10.0 * log10(value); @@ -1407,7 +1445,7 @@ if (m_scale == dBScale || m_scale == MeterScale) { - double thresh = -50.0; + double thresh = m_dBMin; if (v1 == v0) diff = thresh; else {
--- a/layer/WaveformLayer.h Wed Oct 16 12:19:04 2019 +0100 +++ b/layer/WaveformLayer.h Wed Oct 16 12:23:36 2019 +0100 @@ -174,6 +174,8 @@ bool getValueExtents(double &min, double &max, bool &log, QString &unit) const override; + bool getDisplayExtents(double & min, double &max) const override; + bool getYScaleValue(const LayerGeometryProvider *v, int y, double &value, QString &unit) const override; @@ -236,10 +238,13 @@ bool m_showMeans; ChannelMode m_channelMode; int m_channel; + int m_channelCount; Scale m_scale; double m_middleLineHeight; bool m_aggressive; + static double m_dBMin; + mutable std::vector<float> m_effectiveGains; mutable QPixmap *m_cache;