Mercurial > hg > svgui
changeset 1389:1eb560b363e7 spectrogramparam
Make "zoom to region" work sensibly for slice/spectrum layers; ensure that min/max bin are remapped properly when changing fft size
author | Chris Cannam |
---|---|
date | Tue, 13 Nov 2018 14:06:48 +0000 |
parents | 81dda64a7edc |
children | 3c99083a4d83 |
files | layer/Layer.h layer/SliceLayer.cpp layer/SliceLayer.h layer/SpectrumLayer.cpp view/Pane.cpp |
diffstat | 5 files changed, 82 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/Layer.h Tue Nov 13 13:39:01 2018 +0000 +++ b/layer/Layer.h Tue Nov 13 14:06:48 2018 +0000 @@ -414,9 +414,24 @@ virtual bool needsTextLabelHeight() const { return false; } + /** + * Return true if the X axis on the layer is time proportional to + * audio frames, false otherwise. Almost all layer types return + * true here: the exceptions are spectrum and slice layers. + */ virtual bool hasTimeXAxis() const { return true; } /** + * Update the X and Y axis scales, where appropriate, to focus on + * the given rectangular region. This should *only* be overridden + * by layers whose hasTimeXAxis() returns false - the pane handles + * zooming appropriately in every "normal" case. + */ + virtual void zoomToRegion(const LayerGeometryProvider *, QRect) { + return; + } + + /** * Return the minimum and maximum values for the y axis of the * model in this layer, as well as whether the layer is configured * to use a logarithmic y axis display. Also return the unit for
--- a/layer/SliceLayer.cpp Tue Nov 13 13:39:01 2018 +0000 +++ b/layer/SliceLayer.cpp Tue Nov 13 14:06:48 2018 +0000 @@ -74,8 +74,10 @@ connectSignals(m_sliceableModel); - m_minbin = 0; - m_maxbin = m_sliceableModel->getHeight(); + if (m_minbin == 0 && m_maxbin == 0) { + m_minbin = 0; + m_maxbin = m_sliceableModel->getHeight(); + } emit modelReplaced(); emit layerParametersChanged(); @@ -403,18 +405,23 @@ } int mh = m_sliceableModel->getHeight(); + int bin0 = 0; + if (m_maxbin > m_minbin) { + mh = m_maxbin - m_minbin; + bin0 = m_minbin; + } if (m_plotStyle == PlotBlocks) { // Must use actual zero-width pen, too slow otherwise paint.setPen(QPen(getBaseQColor(), 0)); } else { - // Similarly, if there are very many bins here, let's drop to - // a precise 1-pixel-width pen - if (mh > 10000) { - paint.setPen(QPen(getBaseQColor(), 1)); - } else { - paint.setPen(PaintAssistant::scalePen(getBaseQColor())); + // Similarly, if there are very many bins here, we use a + // thinner pen + QPen pen(getBaseQColor(), 1); + if (mh < 10000) { + pen = PaintAssistant::scalePen(pen); } + paint.setPen(pen); } int xorigin = getVerticalScaleWidth(v, true, paint) + 1; @@ -430,13 +437,6 @@ if (h <= 0) return; QPainterPath path; - - int bin0 = 0; - - if (m_maxbin > m_minbin) { - mh = m_maxbin - m_minbin; - bin0 = m_minbin; - } int divisor = 0; @@ -1210,3 +1210,18 @@ return new LinearRangeMapper(0, m_sliceableModel->getHeight(), 0, m_sliceableModel->getHeight(), ""); } + +void +SliceLayer::zoomToRegion(const LayerGeometryProvider *v, QRect rect) +{ + double bin0 = getBinForX(v, rect.x()); + double bin1 = getBinForX(v, rect.x() + rect.width()); + + // ignore y for now... + + SVDEBUG << "SliceLayer::zoomToRegion: zooming to bin range " + << bin0 << " -> " << bin1 << endl; + + setDisplayExtents(floor(bin0), ceil(bin1)); +} +
--- a/layer/SliceLayer.h Tue Nov 13 13:39:01 2018 +0000 +++ b/layer/SliceLayer.h Tue Nov 13 14:06:48 2018 +0000 @@ -75,7 +75,9 @@ virtual void setVerticalZoomStep(int); virtual RangeMapper *getNewVerticalZoomRangeMapper() const; - virtual bool hasTimeXAxis() const { return false; } + virtual bool hasTimeXAxis() const override { return false; } + + virtual void zoomToRegion(const LayerGeometryProvider *, QRect) override; virtual bool isLayerScrollable(const LayerGeometryProvider *) const { return false; }
--- a/layer/SpectrumLayer.cpp Tue Nov 13 13:39:01 2018 +0000 +++ b/layer/SpectrumLayer.cpp Tue Nov 13 14:06:48 2018 +0000 @@ -287,6 +287,16 @@ SpectrumLayer::setWindowSize(int ws) { if (m_windowSize == ws) return; + + SVDEBUG << "setWindowSize: from " << m_windowSize + << " to " << ws << ": updating min and max bins from " + << m_minbin << " and " << m_maxbin << " to "; + + m_minbin = int(round((double(m_minbin) / m_windowSize) * ws)); + m_maxbin = int(round((double(m_maxbin) / m_windowSize) * ws)); + + SVDEBUG << m_minbin << " and " << m_maxbin << endl; + m_windowSize = ws; m_newFFTNeeded = true; emit layerParametersChanged(); @@ -314,8 +324,19 @@ SpectrumLayer::setOversampling(int oversampling) { if (m_oversampling == oversampling) return; + + SVDEBUG << "setOversampling: from " << m_oversampling + << " to " << oversampling << ": updating min and max bins from " + << m_minbin << " and " << m_maxbin << " to "; + + m_minbin = int(round((double(m_minbin) / m_oversampling) * oversampling)); + m_maxbin = int(round((double(m_maxbin) / m_oversampling) * oversampling)); + + SVDEBUG << m_minbin << " and " << m_maxbin << endl; + m_oversampling = oversampling; m_newFFTNeeded = true; + emit layerParametersChanged(); }
--- a/view/Pane.cpp Tue Nov 13 13:39:01 2018 +0000 +++ b/view/Pane.cpp Tue Nov 13 14:06:48 2018 +0000 @@ -27,6 +27,7 @@ #include "layer/WaveformLayer.h" #include "layer/TimeRulerLayer.h" #include "layer/PaintAssistant.h" +#include "ViewProxy.h" // GF: added so we can propagate the mouse move event to the note layer for context handling. #include "layer/LayerFactory.h" @@ -1822,6 +1823,18 @@ int x1 = r.x() + r.width(); int y1 = r.y() + r.height(); + SVDEBUG << "Pane::zoomToRegion: region defined by pixel rect (" + << r.x() << "," << r.y() << "), " << r.width() << "x" << r.height() + << endl; + + Layer *interactionLayer = getInteractionLayer(); + if (interactionLayer && !(interactionLayer->hasTimeXAxis())) { + SVDEBUG << "Interaction layer does not have time X axis - delegating to it to decide what to do" << endl; + ViewProxy proxy(this, effectiveDevicePixelRatio()); + interactionLayer->zoomToRegion(&proxy, r); + return; + } + sv_frame_t newStartFrame = getFrameForX(x0); sv_frame_t newEndFrame = getFrameForX(x1); sv_frame_t dist = newEndFrame - newStartFrame;