Mercurial > hg > svgui
comparison layer/SpectrumLayer.cpp @ 1400:decb7741d036
Different approach to x-coord calculation in slice layer - let's acknowledge that we really do have two different types of model, those whose "bins" are actually at a single value (frequency in the case of the spectrum) and those whose bins are just labels.
author | Chris Cannam |
---|---|
date | Thu, 15 Nov 2018 13:06:38 +0000 |
parents | ba1f0234efa7 |
children | 10e768adaee5 |
comparison
equal
deleted
inserted
replaced
1399:ba1f0234efa7 | 1400:decb7741d036 |
---|---|
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 { | 45 { |
46 m_binAlignment = BinsCentredOnScalePoints; | |
47 | |
46 Preferences *prefs = Preferences::getInstance(); | 48 Preferences *prefs = Preferences::getInstance(); |
47 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), | 49 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), |
48 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); | 50 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); |
49 setWindowType(prefs->getWindowType()); | 51 setWindowType(prefs->getWindowType()); |
50 | 52 |
124 | 126 |
125 if (m_minbin == 0 && m_maxbin == 0) { | 127 if (m_minbin == 0 && m_maxbin == 0) { |
126 m_minbin = 1; | 128 m_minbin = 1; |
127 m_maxbin = newFFT->getHeight(); | 129 m_maxbin = newFFT->getHeight(); |
128 } | 130 } |
129 | 131 |
130 setSliceableModel(newFFT); | 132 setSliceableModel(newFFT); |
131 | 133 |
132 m_biasCurve.clear(); | 134 m_biasCurve.clear(); |
133 for (int i = 0; i < fftSize; ++i) { | 135 for (int i = 0; i < fftSize; ++i) { |
134 m_biasCurve.push_back(1.f / (float(fftSize)/2.f)); | 136 m_biasCurve.push_back(1.f / (float(fftSize)/2.f)); |
294 if (m_windowSize == ws) return; | 296 if (m_windowSize == ws) return; |
295 | 297 |
296 SVDEBUG << "setWindowSize: from " << m_windowSize | 298 SVDEBUG << "setWindowSize: from " << m_windowSize |
297 << " to " << ws << ": updating min and max bins from " | 299 << " to " << ws << ": updating min and max bins from " |
298 << m_minbin << " and " << m_maxbin << " to "; | 300 << m_minbin << " and " << m_maxbin << " to "; |
299 | 301 /* |
300 m_minbin = int(round((double(m_minbin) / m_windowSize) * ws)); | 302 m_minbin = int(round((double(m_minbin) / m_windowSize) * ws)); |
303 */ | |
301 m_maxbin = int(round((double(m_maxbin) / m_windowSize) * ws)); | 304 m_maxbin = int(round((double(m_maxbin) / m_windowSize) * ws)); |
302 | 305 |
306 m_windowSize = ws; | |
307 | |
308 int h = getFFTSize() / 2 + 1; | |
309 if (m_minbin > h) m_minbin = h; | |
310 if (m_maxbin > h) m_maxbin = h; | |
311 | |
303 SVDEBUG << m_minbin << " and " << m_maxbin << endl; | 312 SVDEBUG << m_minbin << " and " << m_maxbin << endl; |
304 | 313 |
305 m_windowSize = ws; | |
306 m_newFFTNeeded = true; | 314 m_newFFTNeeded = true; |
307 emit layerParametersChanged(); | 315 emit layerParametersChanged(); |
308 } | 316 } |
309 | 317 |
310 void | 318 void |
331 if (m_oversampling == oversampling) return; | 339 if (m_oversampling == oversampling) return; |
332 | 340 |
333 SVDEBUG << "setOversampling: from " << m_oversampling | 341 SVDEBUG << "setOversampling: from " << m_oversampling |
334 << " to " << oversampling << ": updating min and max bins from " | 342 << " to " << oversampling << ": updating min and max bins from " |
335 << m_minbin << " and " << m_maxbin << " to "; | 343 << m_minbin << " and " << m_maxbin << " to "; |
336 | 344 /* |
337 m_minbin = int(round((double(m_minbin) / m_oversampling) * oversampling)); | 345 m_minbin = int(round((double(m_minbin) / m_oversampling) * oversampling)); |
346 */ | |
338 m_maxbin = int(round((double(m_maxbin) / m_oversampling) * oversampling)); | 347 m_maxbin = int(round((double(m_maxbin) / m_oversampling) * oversampling)); |
339 | 348 |
349 m_oversampling = oversampling; | |
350 | |
351 int h = getFFTSize() / 2 + 1; | |
352 if (m_minbin > h) m_minbin = h; | |
353 if (m_maxbin > h) m_maxbin = h; | |
354 | |
340 SVDEBUG << m_minbin << " and " << m_maxbin << endl; | 355 SVDEBUG << m_minbin << " and " << m_maxbin << endl; |
341 | 356 |
342 m_oversampling = oversampling; | |
343 m_newFFTNeeded = true; | 357 m_newFFTNeeded = true; |
344 | 358 |
345 emit layerParametersChanged(); | 359 emit layerParametersChanged(); |
346 } | 360 } |
347 | 361 |
374 double | 388 double |
375 SpectrumLayer::getBinForFrequency(double freq) const | 389 SpectrumLayer::getBinForFrequency(double freq) const |
376 { | 390 { |
377 if (!m_sliceableModel) return 0; | 391 if (!m_sliceableModel) return 0; |
378 double bin = (freq * getFFTSize()) / m_sliceableModel->getSampleRate(); | 392 double bin = (freq * getFFTSize()) / m_sliceableModel->getSampleRate(); |
379 // we assume the frequency of a bin corresponds to the centre of | |
380 // its visual range | |
381 bin += 0.5; | |
382 return bin; | 393 return bin; |
383 } | 394 } |
384 | 395 |
385 double | 396 double |
386 SpectrumLayer::getBinForX(const LayerGeometryProvider *v, double x) const | 397 SpectrumLayer::getBinForX(const LayerGeometryProvider *v, double x) const |
394 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const | 405 SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const |
395 { | 406 { |
396 if (!m_sliceableModel) return 0; | 407 if (!m_sliceableModel) return 0; |
397 | 408 |
398 double fmin = getFrequencyForBin(m_minbin); | 409 double fmin = getFrequencyForBin(m_minbin); |
399 | |
400 if (m_binScale == LogBins && m_minbin == 0) { | |
401 // Avoid too much space going to the first bin, but do so in a | |
402 // way that usually avoids us shifting left/right as the | |
403 // window size or oversampling ratio change - i.e. base this | |
404 // on frequency rather than bin number unless we have a lot of | |
405 // very low-resolution content | |
406 fmin = getFrequencyForBin(0.8); | |
407 if (fmin > 6.0) fmin = 6.0; | |
408 } | |
409 | |
410 double fmax = getFrequencyForBin(m_maxbin); | 410 double fmax = getFrequencyForBin(m_maxbin); |
411 | 411 |
412 double freq = getScalePointForX(v, x, fmin, fmax); | 412 double freq = getScalePointForX(v, x, fmin, fmax); |
413 return freq; | 413 return freq; |
414 } | 414 } |
415 | 415 |
416 double | 416 double |
417 SpectrumLayer::getFrequencyForBin(double bin) const | 417 SpectrumLayer::getFrequencyForBin(double bin) const |
418 { | 418 { |
419 if (!m_sliceableModel) return 0; | 419 if (!m_sliceableModel) return 0; |
420 // we assume the frequency of a bin corresponds to the centre of | |
421 // its visual range | |
422 bin -= 0.5; | |
423 double freq = (bin * m_sliceableModel->getSampleRate()) / getFFTSize(); | 420 double freq = (bin * m_sliceableModel->getSampleRate()) / getFFTSize(); |
424 return freq; | 421 return freq; |
425 } | 422 } |
426 | 423 |
427 double | 424 double |
436 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const | 433 SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const |
437 { | 434 { |
438 if (!m_sliceableModel) return 0; | 435 if (!m_sliceableModel) return 0; |
439 | 436 |
440 double fmin = getFrequencyForBin(m_minbin); | 437 double fmin = getFrequencyForBin(m_minbin); |
441 | |
442 if (m_binScale == LogBins && m_minbin == 0) { | |
443 // See comment in getFrequencyForX above | |
444 fmin = getFrequencyForBin(0.8); | |
445 if (fmin > 6.0) fmin = 6.0; | |
446 } | |
447 | |
448 double fmax = getFrequencyForBin(m_maxbin); | 438 double fmax = getFrequencyForBin(m_maxbin); |
449 double x = getXForScalePoint(v, freq, fmin, fmax); | 439 double x = getXForScalePoint(v, freq, fmin, fmax); |
450 | 440 |
451 return x; | 441 return x; |
452 } | 442 } |