Mercurial > hg > svgui
changeset 1403:10e768adaee5
Retain consistent min freq (rather than min bin no) when changing fft parameters in spectrum; scale ffts by window size rather than fft size in case of oversampling, to avoid fading out because of scale factor including zero padding
author | Chris Cannam |
---|---|
date | Thu, 15 Nov 2018 15:08:08 +0000 |
parents | b0eeec95ab5b |
children | a33d38247631 |
files | layer/SliceLayer.cpp layer/SpectrogramLayer.cpp layer/SpectrumLayer.cpp layer/SpectrumLayer.h |
diffstat | 4 files changed, 53 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/SliceLayer.cpp Thu Nov 15 14:18:26 2018 +0000 +++ b/layer/SliceLayer.cpp Thu Nov 15 15:08:08 2018 +0000 @@ -1203,7 +1203,23 @@ m_minbin = int(lrint(min)); m_maxbin = int(lrint(max)); - + + if (m_minbin < 0) { + m_minbin = 0; + } + if (m_maxbin < 0) { + m_maxbin = 0; + } + if (m_minbin > m_sliceableModel->getHeight()) { + m_minbin = m_sliceableModel->getHeight(); + } + if (m_maxbin > m_sliceableModel->getHeight()) { + m_maxbin = m_sliceableModel->getHeight(); + } + if (m_maxbin < m_minbin) { + m_maxbin = m_minbin; + } + emit layerParametersChanged(); return true; } @@ -1238,14 +1254,9 @@ int dist = m_sliceableModel->getHeight() - step; if (dist < 1) dist = 1; double centre = m_minbin + (m_maxbin - m_minbin) / 2.0; - m_minbin = int(lrint(centre - dist/2.0)); - if (m_minbin < 0) m_minbin = 0; - m_maxbin = m_minbin + dist; - if (m_maxbin > m_sliceableModel->getHeight()) m_maxbin = m_sliceableModel->getHeight(); - -// SVDEBUG << "SliceLayer::setVerticalZoomStep(" <<step <<"): after: minbin = " << m_minbin << ", maxbin = " << m_maxbin << endl; - - emit layerParametersChanged(); + int minbin = int(lrint(centre - dist/2.0)); + int maxbin = minbin + dist; + setDisplayExtents(minbin, maxbin); } RangeMapper *
--- a/layer/SpectrogramLayer.cpp Thu Nov 15 14:18:26 2018 +0000 +++ b/layer/SpectrogramLayer.cpp Thu Nov 15 15:08:08 2018 +0000 @@ -1534,7 +1534,7 @@ if (m_colourScale != ColourScaleType::Phase && m_normalization != ColumnNormalization::Hybrid) { - params.scaleFactor *= 2.f / float(getFFTSize()); + params.scaleFactor *= 2.f / float(getWindowSize()); } Preferences::SpectrogramSmoothing smoothing =
--- a/layer/SpectrumLayer.cpp Thu Nov 15 14:18:26 2018 +0000 +++ b/layer/SpectrumLayer.cpp Thu Nov 15 15:08:08 2018 +0000 @@ -41,7 +41,8 @@ m_windowHopLevel(3), m_oversampling(1), m_showPeaks(false), - m_newFFTNeeded(true) + m_newFFTNeeded(true), + m_freqOfMinBin(0.0) { m_binAlignment = BinsCentredOnScalePoints; @@ -126,6 +127,8 @@ if (m_minbin == 0 && m_maxbin == 0) { m_minbin = 1; + m_freqOfMinBin = double(m_minbin * newFFT->getSampleRate()) + / getFFTSize(); m_maxbin = newFFT->getHeight(); } @@ -133,7 +136,9 @@ m_biasCurve.clear(); for (int i = 0; i < fftSize; ++i) { - m_biasCurve.push_back(1.f / (float(fftSize)/2.f)); + // Scale by the window size, not the FFT size, because we + // don't want to scale down by all the zero bins + m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); } m_newFFTNeeded = false; @@ -298,12 +303,12 @@ 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)); + int previousWs = m_windowSize; m_windowSize = ws; + + m_minbin = int(round(getBinForFrequency(m_freqOfMinBin))); + m_maxbin = int(round((double(m_maxbin) / previousWs) * m_windowSize)); int h = getFFTSize() / 2 + 1; if (m_minbin > h) m_minbin = h; @@ -341,12 +346,13 @@ 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)); + int previousOversampling = m_oversampling; m_oversampling = oversampling; + + m_minbin = int(round(getBinForFrequency(m_freqOfMinBin))); + m_maxbin = int(round((double(m_maxbin) / previousOversampling) * + m_oversampling)); int h = getFFTSize() / 2 + 1; if (m_minbin > h) m_minbin = h; @@ -355,7 +361,6 @@ SVDEBUG << m_minbin << " and " << m_maxbin << endl; m_newFFTNeeded = true; - emit layerParametersChanged(); } @@ -385,6 +390,16 @@ } } +bool +SpectrumLayer::setDisplayExtents(double min, double max) +{ + bool result = SliceLayer::setDisplayExtents(min, max); + if (result) { + m_freqOfMinBin = getFrequencyForBin(m_minbin); + } + return result; +} + double SpectrumLayer::getBinForFrequency(double freq) const {
--- a/layer/SpectrumLayer.h Thu Nov 15 14:18:26 2018 +0000 +++ b/layer/SpectrumLayer.h Thu Nov 15 15:08:08 2018 +0000 @@ -68,6 +68,8 @@ virtual void setProperty(const PropertyName &, int value) override; virtual void setProperties(const QXmlAttributes &) override; + virtual bool setDisplayExtents(double min, double max) override; + virtual bool getXScaleValue(const LayerGeometryProvider *v, int x, double &value, QString &unit) const override; @@ -123,6 +125,10 @@ bool m_showPeaks; mutable bool m_newFFTNeeded; + double m_freqOfMinBin; // used to ensure accurate + // alignment when changing + // fft size + mutable QMutex m_fftMutex; void setupFFT();