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