# HG changeset patch # User Chris Cannam # Date 1210257982 0 # Node ID 06b5f110c5d206e1c78607a10a2cd3f6b6cd2f71 # Parent a6408c382616816a749507e7a1bc11c3d41e0e0d * Speed up spectrogram painting by releasing mutex in FFTDataServer while calculating data prior to writing it, and by adding whole-column value query methods to FFT objects * Add paint cache to Thumbwheel -- repaints of this widget were slowing down the whole spectrogram repaint * More uses of MutexLocker (named and with debug) and more profile points * Make startup much quicker some of the time, with OSC server in place diff -r a6408c382616 -r 06b5f110c5d2 layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Tue Apr 29 11:07:14 2008 +0000 +++ b/layer/SpectrogramLayer.cpp Thu May 08 14:46:22 2008 +0000 @@ -1239,6 +1239,8 @@ bool SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const { + Profiler profiler("SpectrogramLayer::getYBinRange"); + int h = v->height(); if (y < 0 || y >= h) return false; @@ -1555,7 +1557,7 @@ m_windowSize, getWindowIncrement(), fftSize, - true, + true, // polar StorageAdviser::SpeedCritical, m_candidateFillStartFrame); @@ -2036,7 +2038,9 @@ float ymag[h]; float ydiv[h]; - float yval[maxbin + 1]; //!!! cache this? + + float yval[maxbin - minbin + 1]; + float values[maxbin - minbin + 1]; size_t increment = getWindowIncrement(); @@ -2044,9 +2048,9 @@ for (size_t q = minbin; q <= maxbin; ++q) { float f0 = (float(q) * sr) / fftSize; - yval[q] = v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, - logarithmic); -// std::cerr << "min: " << minFreq << ", max: " << maxFreq << ", yval[" << q << "]: " << yval[q] << std::endl; + yval[q - minbin] = + v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, + logarithmic); } MagnitudeRange overallMag = m_viewMags[v]; @@ -2079,8 +2083,13 @@ size_t pixels = 0; #endif + Profiler outerprof("SpectrogramLayer::paint: all cols"); + FFTModel::PeakSet peaks; + for (int x = 0; x < w; ++x) { + Profiler innerprof("SpectrogramLayer::paint: 1 pixel column"); + if (runOutOfData) { #ifdef DEBUG_SPECTROGRAM_REPAINT std::cerr << "Run out of data -- dropping out of loop" << std::endl; @@ -2133,20 +2142,34 @@ fftSuspended = true; } + Profiler innerprof2("SpectrogramLayer::paint: 1 data column"); + MagnitudeRange mag; - FFTModel::PeakSet peaks; - if (m_binDisplay == PeakFrequencies && - s < int(fft->getWidth()) - 1) { - peaks = fft->getPeakFrequencies(FFTModel::AllPeaks, - s, - minbin, maxbin - 1); + if (m_binDisplay == PeakFrequencies) { + if (s < int(fft->getWidth()) - 1) { + peaks = fft->getPeakFrequencies(FFTModel::AllPeaks, + s, + minbin, maxbin - 1); + } else { + peaks.clear(); + } } + + if (m_colourScale == PhaseColourScale) { + fft->getPhasesAt(s, values, minbin, maxbin - minbin + 1); + } else if (m_normalizeColumns) { + fft->getNormalizedMagnitudesAt(s, values, minbin, maxbin - minbin + 1); + } else { + fft->getMagnitudesAt(s, values, minbin, maxbin - minbin + 1); + } for (size_t q = minbin; q < maxbin; ++q) { - float y0 = yval[q + 1]; - float y1 = yval[q]; + Profiler innerprof3("SpectrogramLayer::paint: 1 bin"); + + float y0 = yval[q + 1 - minbin]; + float y1 = yval[q - minbin]; if (m_binDisplay == PeakBins) { if (!fft->isLocalPeak(s, q)) continue; @@ -2160,7 +2183,7 @@ continue; } - float sprop = 1.0; + float sprop = 1.f; if (s == s0i) sprop *= (s + 1) - s0; if (s == s1i) sprop *= s1 - s; @@ -2169,11 +2192,24 @@ (peaks[q], displayMinFreq, displayMaxFreq, logarithmic); } - int y0i = int(y0 + 0.001); + int y0i = int(y0 + 0.001f); int y1i = int(y1); - float value; + float value = values[q - minbin]; + + if (m_colourScale != PhaseColourScale) { + if (!m_normalizeColumns) { + value /= (m_fftSize/2.f); + } + mag.sample(value); + value *= m_gain; + } + + float v2 = value; + +//!!! + value = 0.f; if (m_colourScale == PhaseColourScale) { value = fft->getPhaseAt(s, q); } else if (m_normalizeColumns) { @@ -2186,10 +2222,14 @@ value *= m_gain; } + if (value != v2) { + std::cout << "old = " << value << " new = " << v2 << " at y = " << q << std::endl; + } + if (interpolate) { int ypi = y0i; - if (q < maxbin - 1) ypi = int(yval[q + 2]); + if (q < maxbin - 1) ypi = int(yval[q + 2 - minbin]); for (int y = ypi; y <= y1i; ++y) { @@ -2200,7 +2240,7 @@ if (ypi < y0i && y <= y0i) { - float half = float(y0i - ypi) / 2; + float half = float(y0i - ypi) / 2.f; float dist = y - (ypi + half); if (dist >= 0) { @@ -2210,7 +2250,7 @@ } else { if (y1i > y0i) { - float half = float(y1i - y0i) / 2; + float half = float(y1i - y0i) / 2.f; float dist = y - (y0i + half); if (dist >= 0) { @@ -2238,7 +2278,7 @@ if (y < 0 || y >= h) continue; float yprop = sprop; - if (y == y0i) yprop *= (y + 1) - y0; + if (y == y0i) yprop *= (y + 1.f) - y0; if (y == y1i) yprop *= y1 - y; ymag[y] += yprop * value; ydiv[y] += yprop; @@ -2266,6 +2306,8 @@ } } + Profiler drawbufferprof("SpectrogramLayer::paint: set buffer pixels"); + for (int y = 0; y < h; ++y) { if (ydiv[y] > 0.0) { @@ -2301,7 +2343,9 @@ #endif } - Profiler profiler2("SpectrogramLayer::paint: draw image", true); + outerprof.end(); + + Profiler profiler2("SpectrogramLayer::paint: draw image"); if (recreateWholePixmapCache) { std::cerr << "Recreating pixmap cache: width = " << v->width() @@ -2384,6 +2428,8 @@ void SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const { + Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); + QPoint localPos; if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { return; @@ -2823,7 +2869,7 @@ return; } - Profiler profiler("SpectrogramLayer::paintVerticalScale", true); + Profiler profiler("SpectrogramLayer::paintVerticalScale"); //!!! cache this? diff -r a6408c382616 -r 06b5f110c5d2 view/Pane.cpp --- a/view/Pane.cpp Tue Apr 29 11:07:14 2008 +0000 +++ b/view/Pane.cpp Thu May 08 14:46:22 2008 +0000 @@ -87,7 +87,7 @@ void Pane::updateHeadsUpDisplay() { - Profiler profiler("Pane::updateHeadsUpDisplay", true); + Profiler profiler("Pane::updateHeadsUpDisplay"); if (!isVisible()) return; diff -r a6408c382616 -r 06b5f110c5d2 view/View.cpp --- a/view/View.cpp Tue Apr 29 11:07:14 2008 +0000 +++ b/view/View.cpp Thu May 08 14:46:22 2008 +0000 @@ -368,6 +368,8 @@ float maxf, bool logarithmic) const { + Profiler profiler("View::getYForFrequency"); + int h = height(); if (logarithmic) { @@ -1401,7 +1403,7 @@ } else { - i->second->setText(text); +// i->second->setText(text); i->second->setValue(completion); i->second->move(0, ph - i->second->height()); diff -r a6408c382616 -r 06b5f110c5d2 widgets/AudioDial.cpp --- a/widgets/AudioDial.cpp Tue Apr 29 11:07:14 2008 +0000 +++ b/widgets/AudioDial.cpp Thu May 08 14:46:22 2008 +0000 @@ -50,6 +50,8 @@ #include #include +#include "base/Profiler.h" + using std::endl; using std::cerr; @@ -115,6 +117,8 @@ void AudioDial::paintEvent(QPaintEvent *) { + Profiler profiler("AudioDial::paintEvent"); + QPainter paint; float angle = AUDIO_DIAL_MIN // offset diff -r a6408c382616 -r 06b5f110c5d2 widgets/Thumbwheel.cpp --- a/widgets/Thumbwheel.cpp Tue Apr 29 11:07:14 2008 +0000 +++ b/widgets/Thumbwheel.cpp Thu May 08 14:46:22 2008 +0000 @@ -129,6 +129,7 @@ if (m_atDefault) { setValue(m_default); m_atDefault = true; // setValue unsets this + m_cache = QImage(); emit valueChanged(getValue()); } } @@ -145,6 +146,7 @@ if (newValue != getValue()) { setValue(newValue); changed = true; + m_cache = QImage(); } if (changed) emit valueChanged(newValue); m_noMappedUpdate = false; @@ -152,6 +154,7 @@ int v = int(mappedValue); if (v != getValue()) { setValue(v); + m_cache = QImage(); emit valueChanged(v); } } @@ -179,6 +182,7 @@ } m_rotation = float(m_value - m_min) / float(m_max - m_min); + m_cache = QImage(); if (isVisible()) update(); } @@ -188,6 +192,7 @@ if (m_default == m_value) return; setValue(m_default); m_atDefault = true; + m_cache = QImage(); emit valueChanged(getValue()); } @@ -436,7 +441,18 @@ void Thumbwheel::paintEvent(QPaintEvent *) { - Profiler profiler("Thumbwheel::paintEvent", true); + Profiler profiler("Thumbwheel::paintEvent"); + + if (!m_cache.isNull()) { + QPainter paint(this); + paint.drawImage(0, 0, m_cache); + return; + } + + Profiler profiler2("Thumbwheel::paintEvent (no cache)"); + + m_cache = QImage(size(), QImage::Format_ARGB32); + m_cache.fill(Qt::transparent); int bw = 3; @@ -447,7 +463,8 @@ subclip = QRect(bw+1, bw, width() - bw*2 - 2, height() - bw*2); } - QPainter paint(this); + QPainter paint(&m_cache); + paint.setClipRect(rect()); paint.fillRect(subclip, palette().background().color()); paint.setRenderHint(QPainter::Antialiasing, true); @@ -563,6 +580,9 @@ paint.drawRect(QRectF(bw, x0, width() - bw*2, x1 - x0)); } } + + QPainter paint2(this); + paint2.drawImage(0, 0, m_cache); } QSize diff -r a6408c382616 -r 06b5f110c5d2 widgets/Thumbwheel.h --- a/widgets/Thumbwheel.h Tue Apr 29 11:07:14 2008 +0000 +++ b/widgets/Thumbwheel.h Thu May 08 14:46:22 2008 +0000 @@ -17,6 +17,9 @@ #define _THUMBWHEEL_H_ #include +#include + +#include class RangeMapper; @@ -92,6 +95,7 @@ float m_clickRotation; bool m_showTooltip; RangeMapper *m_rangeMapper; + QImage m_cache; }; #endif