Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 382:06b5f110c5d2
* 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
author | Chris Cannam |
---|---|
date | Thu, 08 May 2008 14:46:22 +0000 |
parents | e1a9e478b7f2 |
children | b35184d0dfe5 |
comparison
equal
deleted
inserted
replaced
380:a6408c382616 | 382:06b5f110c5d2 |
---|---|
1237 } | 1237 } |
1238 | 1238 |
1239 bool | 1239 bool |
1240 SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const | 1240 SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const |
1241 { | 1241 { |
1242 Profiler profiler("SpectrogramLayer::getYBinRange"); | |
1243 | |
1242 int h = v->height(); | 1244 int h = v->height(); |
1243 if (y < 0 || y >= h) return false; | 1245 if (y < 0 || y >= h) return false; |
1244 | 1246 |
1245 int sr = m_model->getSampleRate(); | 1247 int sr = m_model->getSampleRate(); |
1246 float minf = getEffectiveMinFrequency(); | 1248 float minf = getEffectiveMinFrequency(); |
1553 m_channel, | 1555 m_channel, |
1554 m_windowType, | 1556 m_windowType, |
1555 m_windowSize, | 1557 m_windowSize, |
1556 getWindowIncrement(), | 1558 getWindowIncrement(), |
1557 fftSize, | 1559 fftSize, |
1558 true, | 1560 true, // polar |
1559 StorageAdviser::SpeedCritical, | 1561 StorageAdviser::SpeedCritical, |
1560 m_candidateFillStartFrame); | 1562 m_candidateFillStartFrame); |
1561 | 1563 |
1562 if (!model->isOK()) { | 1564 if (!model->isOK()) { |
1563 QMessageBox::critical | 1565 QMessageBox::critical |
2034 | 2036 |
2035 // std::cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << std::endl; | 2037 // std::cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << std::endl; |
2036 | 2038 |
2037 float ymag[h]; | 2039 float ymag[h]; |
2038 float ydiv[h]; | 2040 float ydiv[h]; |
2039 float yval[maxbin + 1]; //!!! cache this? | 2041 |
2042 float yval[maxbin - minbin + 1]; | |
2043 float values[maxbin - minbin + 1]; | |
2040 | 2044 |
2041 size_t increment = getWindowIncrement(); | 2045 size_t increment = getWindowIncrement(); |
2042 | 2046 |
2043 bool logarithmic = (m_frequencyScale == LogFrequencyScale); | 2047 bool logarithmic = (m_frequencyScale == LogFrequencyScale); |
2044 | 2048 |
2045 for (size_t q = minbin; q <= maxbin; ++q) { | 2049 for (size_t q = minbin; q <= maxbin; ++q) { |
2046 float f0 = (float(q) * sr) / fftSize; | 2050 float f0 = (float(q) * sr) / fftSize; |
2047 yval[q] = v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, | 2051 yval[q - minbin] = |
2048 logarithmic); | 2052 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, |
2049 // std::cerr << "min: " << minFreq << ", max: " << maxFreq << ", yval[" << q << "]: " << yval[q] << std::endl; | 2053 logarithmic); |
2050 } | 2054 } |
2051 | 2055 |
2052 MagnitudeRange overallMag = m_viewMags[v]; | 2056 MagnitudeRange overallMag = m_viewMags[v]; |
2053 bool overallMagChanged = false; | 2057 bool overallMagChanged = false; |
2054 | 2058 |
2077 | 2081 |
2078 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2082 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2079 size_t pixels = 0; | 2083 size_t pixels = 0; |
2080 #endif | 2084 #endif |
2081 | 2085 |
2086 Profiler outerprof("SpectrogramLayer::paint: all cols"); | |
2087 FFTModel::PeakSet peaks; | |
2088 | |
2082 for (int x = 0; x < w; ++x) { | 2089 for (int x = 0; x < w; ++x) { |
2090 | |
2091 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column"); | |
2083 | 2092 |
2084 if (runOutOfData) { | 2093 if (runOutOfData) { |
2085 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2094 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2086 std::cerr << "Run out of data -- dropping out of loop" << std::endl; | 2095 std::cerr << "Run out of data -- dropping out of loop" << std::endl; |
2087 #endif | 2096 #endif |
2131 if (!fftSuspended) { | 2140 if (!fftSuspended) { |
2132 fft->suspendWrites(); | 2141 fft->suspendWrites(); |
2133 fftSuspended = true; | 2142 fftSuspended = true; |
2134 } | 2143 } |
2135 | 2144 |
2145 Profiler innerprof2("SpectrogramLayer::paint: 1 data column"); | |
2146 | |
2136 MagnitudeRange mag; | 2147 MagnitudeRange mag; |
2137 | 2148 |
2138 FFTModel::PeakSet peaks; | 2149 if (m_binDisplay == PeakFrequencies) { |
2139 if (m_binDisplay == PeakFrequencies && | 2150 if (s < int(fft->getWidth()) - 1) { |
2140 s < int(fft->getWidth()) - 1) { | 2151 peaks = fft->getPeakFrequencies(FFTModel::AllPeaks, |
2141 peaks = fft->getPeakFrequencies(FFTModel::AllPeaks, | 2152 s, |
2142 s, | 2153 minbin, maxbin - 1); |
2143 minbin, maxbin - 1); | 2154 } else { |
2155 peaks.clear(); | |
2156 } | |
2144 } | 2157 } |
2158 | |
2159 if (m_colourScale == PhaseColourScale) { | |
2160 fft->getPhasesAt(s, values, minbin, maxbin - minbin + 1); | |
2161 } else if (m_normalizeColumns) { | |
2162 fft->getNormalizedMagnitudesAt(s, values, minbin, maxbin - minbin + 1); | |
2163 } else { | |
2164 fft->getMagnitudesAt(s, values, minbin, maxbin - minbin + 1); | |
2165 } | |
2145 | 2166 |
2146 for (size_t q = minbin; q < maxbin; ++q) { | 2167 for (size_t q = minbin; q < maxbin; ++q) { |
2147 | 2168 |
2148 float y0 = yval[q + 1]; | 2169 Profiler innerprof3("SpectrogramLayer::paint: 1 bin"); |
2149 float y1 = yval[q]; | 2170 |
2171 float y0 = yval[q + 1 - minbin]; | |
2172 float y1 = yval[q - minbin]; | |
2150 | 2173 |
2151 if (m_binDisplay == PeakBins) { | 2174 if (m_binDisplay == PeakBins) { |
2152 if (!fft->isLocalPeak(s, q)) continue; | 2175 if (!fft->isLocalPeak(s, q)) continue; |
2153 } | 2176 } |
2154 if (m_binDisplay == PeakFrequencies) { | 2177 if (m_binDisplay == PeakFrequencies) { |
2158 if (m_threshold != 0.f && | 2181 if (m_threshold != 0.f && |
2159 !fft->isOverThreshold(s, q, m_threshold * (m_fftSize/2))) { | 2182 !fft->isOverThreshold(s, q, m_threshold * (m_fftSize/2))) { |
2160 continue; | 2183 continue; |
2161 } | 2184 } |
2162 | 2185 |
2163 float sprop = 1.0; | 2186 float sprop = 1.f; |
2164 if (s == s0i) sprop *= (s + 1) - s0; | 2187 if (s == s0i) sprop *= (s + 1) - s0; |
2165 if (s == s1i) sprop *= s1 - s; | 2188 if (s == s1i) sprop *= s1 - s; |
2166 | 2189 |
2167 if (m_binDisplay == PeakFrequencies) { | 2190 if (m_binDisplay == PeakFrequencies) { |
2168 y0 = y1 = v->getYForFrequency | 2191 y0 = y1 = v->getYForFrequency |
2169 (peaks[q], displayMinFreq, displayMaxFreq, logarithmic); | 2192 (peaks[q], displayMinFreq, displayMaxFreq, logarithmic); |
2170 } | 2193 } |
2171 | 2194 |
2172 int y0i = int(y0 + 0.001); | 2195 int y0i = int(y0 + 0.001f); |
2173 int y1i = int(y1); | 2196 int y1i = int(y1); |
2174 | 2197 |
2175 float value; | 2198 float value = values[q - minbin]; |
2199 | |
2200 if (m_colourScale != PhaseColourScale) { | |
2201 if (!m_normalizeColumns) { | |
2202 value /= (m_fftSize/2.f); | |
2203 } | |
2204 mag.sample(value); | |
2205 value *= m_gain; | |
2206 } | |
2207 | |
2208 float v2 = value; | |
2209 | |
2210 //!!! | |
2176 | 2211 |
2212 value = 0.f; | |
2177 if (m_colourScale == PhaseColourScale) { | 2213 if (m_colourScale == PhaseColourScale) { |
2178 value = fft->getPhaseAt(s, q); | 2214 value = fft->getPhaseAt(s, q); |
2179 } else if (m_normalizeColumns) { | 2215 } else if (m_normalizeColumns) { |
2180 value = fft->getNormalizedMagnitudeAt(s, q); | 2216 value = fft->getNormalizedMagnitudeAt(s, q); |
2181 mag.sample(value); | 2217 mag.sample(value); |
2184 value = fft->getMagnitudeAt(s, q) / (m_fftSize/2); | 2220 value = fft->getMagnitudeAt(s, q) / (m_fftSize/2); |
2185 mag.sample(value); | 2221 mag.sample(value); |
2186 value *= m_gain; | 2222 value *= m_gain; |
2187 } | 2223 } |
2188 | 2224 |
2225 if (value != v2) { | |
2226 std::cout << "old = " << value << " new = " << v2 << " at y = " << q << std::endl; | |
2227 } | |
2228 | |
2189 if (interpolate) { | 2229 if (interpolate) { |
2190 | 2230 |
2191 int ypi = y0i; | 2231 int ypi = y0i; |
2192 if (q < maxbin - 1) ypi = int(yval[q + 2]); | 2232 if (q < maxbin - 1) ypi = int(yval[q + 2 - minbin]); |
2193 | 2233 |
2194 for (int y = ypi; y <= y1i; ++y) { | 2234 for (int y = ypi; y <= y1i; ++y) { |
2195 | 2235 |
2196 if (y < 0 || y >= h) continue; | 2236 if (y < 0 || y >= h) continue; |
2197 | 2237 |
2198 float yprop = sprop; | 2238 float yprop = sprop; |
2199 float iprop = yprop; | 2239 float iprop = yprop; |
2200 | 2240 |
2201 if (ypi < y0i && y <= y0i) { | 2241 if (ypi < y0i && y <= y0i) { |
2202 | 2242 |
2203 float half = float(y0i - ypi) / 2; | 2243 float half = float(y0i - ypi) / 2.f; |
2204 float dist = y - (ypi + half); | 2244 float dist = y - (ypi + half); |
2205 | 2245 |
2206 if (dist >= 0) { | 2246 if (dist >= 0) { |
2207 iprop = (iprop * dist) / half; | 2247 iprop = (iprop * dist) / half; |
2208 ymag[y] += iprop * value; | 2248 ymag[y] += iprop * value; |
2209 } | 2249 } |
2210 } else { | 2250 } else { |
2211 if (y1i > y0i) { | 2251 if (y1i > y0i) { |
2212 | 2252 |
2213 float half = float(y1i - y0i) / 2; | 2253 float half = float(y1i - y0i) / 2.f; |
2214 float dist = y - (y0i + half); | 2254 float dist = y - (y0i + half); |
2215 | 2255 |
2216 if (dist >= 0) { | 2256 if (dist >= 0) { |
2217 iprop = (iprop * (half - dist)) / half; | 2257 iprop = (iprop * (half - dist)) / half; |
2218 } | 2258 } |
2236 for (int y = y0i; y <= y1i; ++y) { | 2276 for (int y = y0i; y <= y1i; ++y) { |
2237 | 2277 |
2238 if (y < 0 || y >= h) continue; | 2278 if (y < 0 || y >= h) continue; |
2239 | 2279 |
2240 float yprop = sprop; | 2280 float yprop = sprop; |
2241 if (y == y0i) yprop *= (y + 1) - y0; | 2281 if (y == y0i) yprop *= (y + 1.f) - y0; |
2242 if (y == y1i) yprop *= y1 - y; | 2282 if (y == y1i) yprop *= y1 - y; |
2243 ymag[y] += yprop * value; | 2283 ymag[y] += yprop * value; |
2244 ydiv[y] += yprop; | 2284 ydiv[y] += yprop; |
2245 } | 2285 } |
2246 } | 2286 } |
2264 #endif | 2304 #endif |
2265 } | 2305 } |
2266 } | 2306 } |
2267 } | 2307 } |
2268 | 2308 |
2309 Profiler drawbufferprof("SpectrogramLayer::paint: set buffer pixels"); | |
2310 | |
2269 for (int y = 0; y < h; ++y) { | 2311 for (int y = 0; y < h; ++y) { |
2270 | 2312 |
2271 if (ydiv[y] > 0.0) { | 2313 if (ydiv[y] > 0.0) { |
2272 | 2314 |
2273 unsigned char pixel = 0; | 2315 unsigned char pixel = 0; |
2299 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2341 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2300 std::cerr << "Overall mag unchanged at [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; | 2342 std::cerr << "Overall mag unchanged at [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl; |
2301 #endif | 2343 #endif |
2302 } | 2344 } |
2303 | 2345 |
2304 Profiler profiler2("SpectrogramLayer::paint: draw image", true); | 2346 outerprof.end(); |
2347 | |
2348 Profiler profiler2("SpectrogramLayer::paint: draw image"); | |
2305 | 2349 |
2306 if (recreateWholePixmapCache) { | 2350 if (recreateWholePixmapCache) { |
2307 std::cerr << "Recreating pixmap cache: width = " << v->width() | 2351 std::cerr << "Recreating pixmap cache: width = " << v->width() |
2308 << ", height = " << h << std::endl; | 2352 << ", height = " << h << std::endl; |
2309 cache.pixmap = QPixmap(v->width(), h); | 2353 cache.pixmap = QPixmap(v->width(), h); |
2382 } | 2426 } |
2383 | 2427 |
2384 void | 2428 void |
2385 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const | 2429 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const |
2386 { | 2430 { |
2431 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); | |
2432 | |
2387 QPoint localPos; | 2433 QPoint localPos; |
2388 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { | 2434 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { |
2389 return; | 2435 return; |
2390 } | 2436 } |
2391 | 2437 |
2821 { | 2867 { |
2822 if (!m_model || !m_model->isOK()) { | 2868 if (!m_model || !m_model->isOK()) { |
2823 return; | 2869 return; |
2824 } | 2870 } |
2825 | 2871 |
2826 Profiler profiler("SpectrogramLayer::paintVerticalScale", true); | 2872 Profiler profiler("SpectrogramLayer::paintVerticalScale"); |
2827 | 2873 |
2828 //!!! cache this? | 2874 //!!! cache this? |
2829 | 2875 |
2830 int h = rect.height(), w = rect.width(); | 2876 int h = rect.height(), w = rect.width(); |
2831 | 2877 |