Mercurial > hg > svgui
comparison layer/SpectrumLayer.cpp @ 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 | decb7741d036 |
children | c8a6fd3f9dff |
comparison
equal
deleted
inserted
replaced
1402:b0eeec95ab5b | 1403:10e768adaee5 |
---|---|
39 m_windowSize(4096), | 39 m_windowSize(4096), |
40 m_windowType(HanningWindow), | 40 m_windowType(HanningWindow), |
41 m_windowHopLevel(3), | 41 m_windowHopLevel(3), |
42 m_oversampling(1), | 42 m_oversampling(1), |
43 m_showPeaks(false), | 43 m_showPeaks(false), |
44 m_newFFTNeeded(true) | 44 m_newFFTNeeded(true), |
45 m_freqOfMinBin(0.0) | |
45 { | 46 { |
46 m_binAlignment = BinsCentredOnScalePoints; | 47 m_binAlignment = BinsCentredOnScalePoints; |
47 | 48 |
48 Preferences *prefs = Preferences::getInstance(); | 49 Preferences *prefs = Preferences::getInstance(); |
49 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), | 50 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), |
124 getWindowIncrement(), | 125 getWindowIncrement(), |
125 fftSize); | 126 fftSize); |
126 | 127 |
127 if (m_minbin == 0 && m_maxbin == 0) { | 128 if (m_minbin == 0 && m_maxbin == 0) { |
128 m_minbin = 1; | 129 m_minbin = 1; |
130 m_freqOfMinBin = double(m_minbin * newFFT->getSampleRate()) | |
131 / getFFTSize(); | |
129 m_maxbin = newFFT->getHeight(); | 132 m_maxbin = newFFT->getHeight(); |
130 } | 133 } |
131 | 134 |
132 setSliceableModel(newFFT); | 135 setSliceableModel(newFFT); |
133 | 136 |
134 m_biasCurve.clear(); | 137 m_biasCurve.clear(); |
135 for (int i = 0; i < fftSize; ++i) { | 138 for (int i = 0; i < fftSize; ++i) { |
136 m_biasCurve.push_back(1.f / (float(fftSize)/2.f)); | 139 // Scale by the window size, not the FFT size, because we |
140 // don't want to scale down by all the zero bins | |
141 m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); | |
137 } | 142 } |
138 | 143 |
139 m_newFFTNeeded = false; | 144 m_newFFTNeeded = false; |
140 } | 145 } |
141 | 146 |
296 if (m_windowSize == ws) return; | 301 if (m_windowSize == ws) return; |
297 | 302 |
298 SVDEBUG << "setWindowSize: from " << m_windowSize | 303 SVDEBUG << "setWindowSize: from " << m_windowSize |
299 << " to " << ws << ": updating min and max bins from " | 304 << " to " << ws << ": updating min and max bins from " |
300 << m_minbin << " and " << m_maxbin << " to "; | 305 << m_minbin << " and " << m_maxbin << " to "; |
301 /* | 306 |
302 m_minbin = int(round((double(m_minbin) / m_windowSize) * ws)); | 307 int previousWs = m_windowSize; |
303 */ | |
304 m_maxbin = int(round((double(m_maxbin) / m_windowSize) * ws)); | |
305 | |
306 m_windowSize = ws; | 308 m_windowSize = ws; |
309 | |
310 m_minbin = int(round(getBinForFrequency(m_freqOfMinBin))); | |
311 m_maxbin = int(round((double(m_maxbin) / previousWs) * m_windowSize)); | |
307 | 312 |
308 int h = getFFTSize() / 2 + 1; | 313 int h = getFFTSize() / 2 + 1; |
309 if (m_minbin > h) m_minbin = h; | 314 if (m_minbin > h) m_minbin = h; |
310 if (m_maxbin > h) m_maxbin = h; | 315 if (m_maxbin > h) m_maxbin = h; |
311 | 316 |
339 if (m_oversampling == oversampling) return; | 344 if (m_oversampling == oversampling) return; |
340 | 345 |
341 SVDEBUG << "setOversampling: from " << m_oversampling | 346 SVDEBUG << "setOversampling: from " << m_oversampling |
342 << " to " << oversampling << ": updating min and max bins from " | 347 << " to " << oversampling << ": updating min and max bins from " |
343 << m_minbin << " and " << m_maxbin << " to "; | 348 << m_minbin << " and " << m_maxbin << " to "; |
344 /* | 349 |
345 m_minbin = int(round((double(m_minbin) / m_oversampling) * oversampling)); | 350 int previousOversampling = m_oversampling; |
346 */ | |
347 m_maxbin = int(round((double(m_maxbin) / m_oversampling) * oversampling)); | |
348 | |
349 m_oversampling = oversampling; | 351 m_oversampling = oversampling; |
352 | |
353 m_minbin = int(round(getBinForFrequency(m_freqOfMinBin))); | |
354 m_maxbin = int(round((double(m_maxbin) / previousOversampling) * | |
355 m_oversampling)); | |
350 | 356 |
351 int h = getFFTSize() / 2 + 1; | 357 int h = getFFTSize() / 2 + 1; |
352 if (m_minbin > h) m_minbin = h; | 358 if (m_minbin > h) m_minbin = h; |
353 if (m_maxbin > h) m_maxbin = h; | 359 if (m_maxbin > h) m_maxbin = h; |
354 | 360 |
355 SVDEBUG << m_minbin << " and " << m_maxbin << endl; | 361 SVDEBUG << m_minbin << " and " << m_maxbin << endl; |
356 | 362 |
357 m_newFFTNeeded = true; | 363 m_newFFTNeeded = true; |
358 | |
359 emit layerParametersChanged(); | 364 emit layerParametersChanged(); |
360 } | 365 } |
361 | 366 |
362 int | 367 int |
363 SpectrumLayer::getOversampling() const | 368 SpectrumLayer::getOversampling() const |
381 SVDEBUG << "SpectrumLayer::preferenceChanged: Window type changed to " | 386 SVDEBUG << "SpectrumLayer::preferenceChanged: Window type changed to " |
382 << type << endl; | 387 << type << endl; |
383 setWindowType(type); | 388 setWindowType(type); |
384 return; | 389 return; |
385 } | 390 } |
391 } | |
392 | |
393 bool | |
394 SpectrumLayer::setDisplayExtents(double min, double max) | |
395 { | |
396 bool result = SliceLayer::setDisplayExtents(min, max); | |
397 if (result) { | |
398 m_freqOfMinBin = getFrequencyForBin(m_minbin); | |
399 } | |
400 return result; | |
386 } | 401 } |
387 | 402 |
388 double | 403 double |
389 SpectrumLayer::getBinForFrequency(double freq) const | 404 SpectrumLayer::getBinForFrequency(double freq) const |
390 { | 405 { |