Improve spectrum analyzer performance by caching most used computations (#6003)

This commit is contained in:
Martin Pavelek
2022-01-06 04:09:46 +01:00
committed by GitHub
parent 13e17496dc
commit 13e55101f0
3 changed files with 50 additions and 13 deletions

View File

@@ -47,7 +47,13 @@ SaSpectrumView::SaSpectrumView(SaControls *controls, SaProcessor *processor, QWi
m_controls(controls),
m_processor(processor),
m_freezeRequest(false),
m_frozen(false)
m_frozen(false),
m_cachedRangeMin(-1),
m_cachedRangeMax(-1),
m_cachedLogX(true),
m_cachedDisplayWidth(0),
m_cachedBinCount(0),
m_cachedSampleRate(0)
{
setMinimumSize(360, 170);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
@@ -69,6 +75,9 @@ SaSpectrumView::SaSpectrumView(SaControls *controls, SaProcessor *processor, QWi
m_cursor = QPointF(0, 0);
// Initialize the size of bin → pixel X position LUT to the maximum allowed number of bins + 1.
m_cachedBinToX.resize(FFT_BLOCK_SIZES.back() / 2 + 2);
#ifdef SA_DEBUG
m_execution_avg = m_path_avg = m_draw_avg = 0;
#endif
@@ -348,10 +357,31 @@ QPainterPath SaSpectrumView::makePath(std::vector<float> &displayBuffer, float r
// Bins falling to interval [x_start, x_next) contribute to a single point.
float max = m_displayBottom;
float x_start = -1; // lower bound of currently constructed point
// Speed up bin → x position translation by building a LUT cache.
// Update the cache only when range or display width are changed.
float rangeMin = m_processor->getFreqRangeMin(m_controls->m_logXModel.value());
float rangeMax = m_processor->getFreqRangeMax();
if (rangeMin != m_cachedRangeMin || rangeMax != m_cachedRangeMax || m_displayWidth != m_cachedDisplayWidth ||
m_controls->m_logXModel.value() != m_cachedLogX || m_processor->binCount() + 1 != m_cachedBinCount ||
m_processor->getSampleRate() != m_cachedSampleRate)
{
m_cachedRangeMin = rangeMin;
m_cachedRangeMax = rangeMax;
m_cachedDisplayWidth = m_displayWidth;
m_cachedLogX = m_controls->m_logXModel.value();
m_cachedBinCount = m_processor->binCount() + 1;
m_cachedSampleRate = m_processor->getSampleRate();
for (unsigned int n = 0; n < m_cachedBinCount; n++)
{
m_cachedBinToX[n] = freqToXPixel(binToFreq(n), m_displayWidth);
}
}
for (unsigned int n = 0; n < m_processor->binCount(); n++)
{
float x = freqToXPixel(binToFreq(n), m_displayWidth);
float x_next = freqToXPixel(binToFreq(n + 1), m_displayWidth);
float x = m_cachedBinToX[n];
float x_next = m_cachedBinToX[n + 1];
float y = ampToYPixel(displayBuffer[n], m_displayBottom);
// consider making a point only if x falls within display bounds