Mercurial > hg > svgui
diff layer/SpectrogramLayer.cpp @ 187:e7cf6044c2a0
* better icon
* support range mappers in thumbwheel
* supply range mapper for vertical zoom from spectrogram
* fix bug in fftmodel for scaled ffts
* make the various widgets all respond to double-click for edit, middle-click
for reset, ctrl-left-click for reset
author | Chris Cannam |
---|---|
date | Fri, 12 Jan 2007 14:49:18 +0000 |
parents | 3a6fea0abf56 |
children | dd573e090eed |
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp Fri Jan 05 15:49:10 2007 +0000 +++ b/layer/SpectrogramLayer.cpp Fri Jan 12 14:49:18 2007 +0000 @@ -725,6 +725,8 @@ { if (m_minFrequency == mf) return; + std::cerr << "SpectrogramLayer::setMinFrequency: " << mf << std::endl; + invalidatePixmapCaches(); invalidateMagnitudes(); @@ -744,6 +746,8 @@ { if (m_maxFrequency == mf) return; + std::cerr << "SpectrogramLayer::setMaxFrequency: " << mf << std::endl; + invalidatePixmapCaches(); invalidateMagnitudes(); @@ -1595,7 +1599,7 @@ m_fftModels.erase(v); } else { #ifdef DEBUG_SPECTROGRAM_REPAINT - std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model" << std::endl; + std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[v].first->getHeight() << std::endl; #endif return m_fftModels[v].first; } @@ -2293,6 +2297,7 @@ { min = getEffectiveMinFrequency(); max = getEffectiveMaxFrequency(); + std::cerr << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << std::endl; return true; } @@ -2300,6 +2305,9 @@ SpectrogramLayer::setDisplayExtents(float min, float max) { if (!m_model) return false; + + std::cerr << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << std::endl; + if (min < 0) min = 0; if (max > m_model->getSampleRate()/2) max = m_model->getSampleRate()/2; @@ -2806,38 +2814,73 @@ } } +class SpectrogramRangeMapper : public RangeMapper +{ +public: + SpectrogramRangeMapper(int sr, int fftsize) : +// m_dist((float(sr) / 2) - (float(sr) / fftsize)), + m_dist(float(sr) / 2), + m_s2(sqrtf(sqrtf(2))) { } + ~SpectrogramRangeMapper() { } + + virtual int getPositionForValue(float value) const { + + float dist = m_dist; + + int n = 0; + int discard = 0; + + while (dist > (value + 0.00001) && dist > 0.1f) { + dist /= m_s2; + ++n; + } + + return n; + } + + virtual float getValueForPosition(int position) const { + + // Vertical zoom step 0 shows the entire range from DC -> + // Nyquist frequency. Step 1 shows 2^(1/4) of the range of + // step 0, and so on until the visible range is smaller than + // the frequency step between bins at the current fft size. + + float dist = m_dist; + + int n = 0; + while (n < position) { + dist /= m_s2; + ++n; + } + + return dist; + } + + virtual QString getUnit() const { return "Hz"; } + +protected: + float m_dist; + float m_s2; +}; + int SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const { - // Vertical zoom step 0 shows the entire range from DC -> Nyquist - // frequency. Step 1 shows 2^(1/4) of the range of step 0, and so - // on until the visible range is smaller than the frequency step - // between bins at the current fft size. - if (!m_model) return 0; + + int sr = m_model->getSampleRate(); + + SpectrogramRangeMapper mapper(sr, m_fftSize); + +// int maxStep = mapper.getPositionForValue((float(sr) / m_fftSize) + 0.001); + int maxStep = mapper.getPositionForValue(0); + int minStep = mapper.getPositionForValue(float(sr) / 2); - float min, max; - int sr = m_model->getSampleRate(); - min = float(sr) / m_fftSize; - max = float(sr) / 2; - - float dist = max - min; - - int n = 0; - defaultStep = 0; - bool haveDefault = false; - float s2 = sqrtf(sqrtf(2)); - while (dist > min) { - if (!haveDefault && max <= m_initialMaxFrequency) { - defaultStep = n; - haveDefault = true; - } - ++n; - dist /= s2; - max = min + dist; - } - - return n; + defaultStep = mapper.getPositionForValue(m_initialMaxFrequency) - minStep; + + std::cerr << "SpectrogramLayer::getVerticalZoomSteps: " << maxStep - minStep << " (" << maxStep <<"-" << minStep << "), default is " << defaultStep << " (from initial max freq " << m_initialMaxFrequency << ")" << std::endl; + + return maxStep - minStep; } int @@ -2848,23 +2891,9 @@ float dmin, dmax; getDisplayExtents(dmin, dmax); - float mmin, mmax; - int sr = m_model->getSampleRate(); - mmin = float(sr) / m_fftSize; - mmax = float(sr) / 2; - - float mdist = mmax - mmin; - float ddist = dmax - dmin; - - int n = 0; - int discard = 0; - int m = getVerticalZoomSteps(discard); - float s2 = sqrtf(sqrtf(2)); - while (mdist > ddist) { - if (++n > m) break; - mdist /= s2; - } - + SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize); + int n = mapper.getPositionForValue(dmax - dmin); + std::cerr << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << std::endl; return n; } @@ -2873,32 +2902,42 @@ { //!!! does not do the right thing for log scale + if (!m_model) return; + float dmin, dmax; getDisplayExtents(dmin, dmax); - float mmin, mmax; int sr = m_model->getSampleRate(); - mmin = float(sr) / m_fftSize; - mmax = float(sr) / 2; - - float ddist = mmax - mmin; - - int n = 0; - float s2 = sqrtf(sqrtf(2)); - while (n < step) { - ddist /= s2; - ++n; - } + SpectrogramRangeMapper mapper(sr, m_fftSize); + float ddist = mapper.getValueForPosition(step); float dmid = (dmax + dmin) / 2; float newmin = dmid - ddist / 2; float newmax = dmid + ddist / 2; + + float mmin, mmax; + mmin = 0; + mmax = float(sr) / 2; - if (newmin < mmin) newmin = mmin; - if (newmax > mmax) newmax = mmax; + if (newmin < mmin) { + newmax += (mmin - newmin); + newmin = mmin; + } + if (newmax > mmax) { + newmax = mmax; + } - setMinFrequency(newmin); - setMaxFrequency(newmax); + std::cerr << "SpectrogramLayer::setVerticalZoomStep: " << step << ": " << newmin << " -> " << newmax << " (range " << ddist << ")" << std::endl; + + setMinFrequency(int(newmin)); + setMaxFrequency(int(newmax)); +} + +RangeMapper * +SpectrogramLayer::getNewVerticalZoomRangeMapper() const +{ + if (!m_model) return 0; + return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize); } QString @@ -2971,10 +3010,16 @@ if (ok) setThreshold(threshold); size_t minFrequency = attributes.value("minFrequency").toUInt(&ok); - if (ok) setMinFrequency(minFrequency); + if (ok) { + std::cerr << "SpectrogramLayer::setProperties: setting min freq to " << minFrequency << std::endl; + setMinFrequency(minFrequency); + } size_t maxFrequency = attributes.value("maxFrequency").toUInt(&ok); - if (ok) setMaxFrequency(maxFrequency); + if (ok) { + std::cerr << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << std::endl; + setMaxFrequency(maxFrequency); + } ColourScale colourScale = (ColourScale) attributes.value("colourScale").toInt(&ok);