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 { | 
