comparison layer/SpectrogramLayer.cpp @ 488:5cd6f0d3f42d

* Re-enable peak frequencies display in spectrogram
author Chris Cannam
date Thu, 05 Feb 2009 17:33:21 +0000
parents 6a5327c0a40f
children 363157772fbd
comparison
equal deleted inserted replaced
487:6a5327c0a40f 488:5cd6f0d3f42d
2040 } 2040 }
2041 2041
2042 if (paintBlockWidth < 20) paintBlockWidth = 20; 2042 if (paintBlockWidth < 20) paintBlockWidth = 20;
2043 } 2043 }
2044 2044
2045 #ifdef DEBUG_SPECTROGRAM_REPAINT 2045 //#ifdef DEBUG_SPECTROGRAM_REPAINT
2046 std::cerr << "[" << this << "]: last paint width: " << m_lastPaintBlockWidth << ", last paint time: " << m_lastPaintTime << ", new paint width: " << paintBlockWidth << std::endl; 2046 std::cerr << "[" << this << "]: last paint width: " << m_lastPaintBlockWidth << ", last paint time: " << m_lastPaintTime << ", new paint width: " << paintBlockWidth << std::endl;
2047 #endif 2047 //#endif
2048 2048
2049 // We always paint the full height when refreshing the cache. 2049 // We always paint the full height when refreshing the cache.
2050 // Smaller heights can be used when painting direct from cache 2050 // Smaller heights can be used when painting direct from cache
2051 // (further up in this function), but we want to ensure the cache 2051 // (further up in this function), but we want to ensure the cache
2052 // is coherent without having to worry about vertical matching of 2052 // is coherent without having to worry about vertical matching of
2182 // std::cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << std::endl; 2182 // std::cerr << "(giving actual minFreq " << minFreq << " and display minFreq " << displayMinFreq << ")" << std::endl;
2183 2183
2184 size_t increment = getWindowIncrement(); 2184 size_t increment = getWindowIncrement();
2185 2185
2186 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 2186 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
2187 2187 /*
2188 float yforbin[maxbin - minbin + 1]; 2188 float yforbin[maxbin - minbin + 1];
2189 2189
2190 for (size_t q = minbin; q <= maxbin; ++q) { 2190 for (size_t q = minbin; q <= maxbin; ++q) {
2191 float f0 = (float(q) * sr) / fftSize; 2191 float f0 = (float(q) * sr) / fftSize;
2192 yforbin[q - minbin] = 2192 yforbin[q - minbin] =
2193 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, 2193 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq,
2194 logarithmic); 2194 logarithmic);
2195 } 2195 }
2196 2196 */
2197 MagnitudeRange overallMag = m_viewMags[v]; 2197 MagnitudeRange overallMag = m_viewMags[v];
2198 bool overallMagChanged = false; 2198 bool overallMagChanged = false;
2199 2199
2200 bool fftSuspended = false; 2200 bool fftSuspended = false;
2201 2201
2296 m_drawBuffer.setColor(pixel, m_palette.getColour(pixel).rgb()); 2296 m_drawBuffer.setColor(pixel, m_palette.getColour(pixel).rgb());
2297 } 2297 }
2298 2298
2299 m_drawBuffer.fill(0); 2299 m_drawBuffer.fill(0);
2300 2300
2301 for (int y = 0; y < h; ++y) { 2301 if (m_binDisplay != PeakFrequencies) {
2302 float q0 = 0, q1 = 0; 2302
2303 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) { 2303 for (int y = 0; y < h; ++y) {
2304 binfory[y] = -1; 2304 float q0 = 0, q1 = 0;
2305 } else { 2305 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) {
2306 binfory[y] = int(q0 + 0.0001); 2306 binfory[y] = -1;
2307 cerr << "binfory[" << y << "] = " << binfory[y] << endl; 2307 } else {
2308 } 2308 binfory[y] = int(q0 + 0.0001);
2309 } 2309 // cerr << "binfory[" << y << "] = " << binfory[y] << endl;
2310 2310 }
2311 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache); 2311 }
2312
2313 paintDrawBuffer(v, bufwid, h, binforx, binfory, usePeaksCache);
2314
2315 } else {
2316
2317 paintDrawBufferPeakFrequencies(v, bufwid, h, binforx,
2318 minbin, maxbin,
2319 displayMinFreq, displayMaxFreq,
2320 logarithmic);
2321 }
2312 2322
2313 /* 2323 /*
2314 for (int x = 0; x < w / xPixelRatio; ++x) { 2324 for (int x = 0; x < w / xPixelRatio; ++x) {
2315 2325
2316 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column"); 2326 Profiler innerprof("SpectrogramLayer::paint: 1 pixel column");
2466 2476
2467 //!!! if (fftSuspended) fft->resume(); 2477 //!!! if (fftSuspended) fft->resume();
2468 } 2478 }
2469 2479
2470 bool 2480 bool
2481 SpectrogramLayer::paintDrawBufferPeakFrequencies(View *v,
2482 int w,
2483 int h,
2484 int *binforx,
2485 int minbin,
2486 int maxbin,
2487 float displayMinFreq,
2488 float displayMaxFreq,
2489 bool logarithmic) const
2490 {
2491 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies");
2492
2493 #ifdef DEBUG_SPECTROGRAM_REPAINT
2494 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl;
2495 #endif
2496 if (minbin < 0) minbin = 0;
2497 if (maxbin < 0) maxbin = minbin+1;
2498
2499 FFTModel *fft = getFFTModel(v);
2500 if (!fft) return false;
2501
2502 FFTModel::PeakSet peakfreqs;
2503
2504 int px = -1, psx = -1;
2505 float values[maxbin - minbin + 1];
2506
2507 for (int x = 0; x < w; ++x) {
2508
2509 if (binforx[x] < 0) continue;
2510
2511 float columnMax = 0.f;
2512
2513 int sx0 = binforx[x];
2514 int sx1 = sx0;
2515 if (x+1 < w) sx1 = binforx[x+1];
2516 if (sx0 < 0) sx0 = sx1 - 1;
2517 if (sx0 < 0) continue;
2518 if (sx1 <= sx0) sx1 = sx0 + 1;
2519
2520 for (int sx = sx0; sx < sx1; ++sx) {
2521
2522 if (x == px && sx == psx) continue;
2523 if (sx < 0 || sx >= int(fft->getWidth())) continue;
2524
2525 if (!m_synchronous) {
2526 if (!fft->isColumnAvailable(sx)) {
2527 #ifdef DEBUG_SPECTROGRAM_REPAINT
2528 std::cerr << "Met unavailable column at col " << sx << std::endl;
2529 #endif
2530 return false;
2531 }
2532 }
2533
2534 MagnitudeRange mag;
2535
2536 if (sx != psx) {
2537 peakfreqs = fft->getPeakFrequencies(FFTModel::AllPeaks, sx,
2538 minbin, maxbin - 1);
2539 if (m_colourScale == PhaseColourScale) {
2540 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1);
2541 } else if (m_normalizeColumns) {
2542 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2543 } else {
2544 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2545 }
2546 psx = sx;
2547 }
2548
2549 for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
2550 pi != peakfreqs.end(); ++pi) {
2551
2552 int bin = pi->first;
2553 int freq = pi->second;
2554
2555 if (bin < minbin) continue;
2556 if (bin > maxbin) break;
2557
2558 float value = values[bin - minbin];
2559
2560 if (m_colourScale != PhaseColourScale) {
2561 if (!m_normalizeColumns) {
2562 value /= (m_fftSize/2.f);
2563 }
2564 mag.sample(value);
2565 value *= m_gain;
2566 }
2567
2568 float y = v->getYForFrequency
2569 (freq, displayMinFreq, displayMaxFreq, logarithmic);
2570
2571 if (y < 0 || y >= h) continue;
2572
2573 m_drawBuffer.setPixel(x, y, getDisplayValue(v, value));
2574 }
2575
2576 if (mag.isSet()) {
2577 if (sx >= int(m_columnMags.size())) {
2578 std::cerr << "INTERNAL ERROR: " << sx << " >= "
2579 << m_columnMags.size()
2580 << " at SpectrogramLayer.cpp::paintDrawBuffer"
2581 << std::endl;
2582 }
2583 m_columnMags[sx].sample(mag);
2584 }
2585 }
2586 }
2587
2588 return true;
2589 }
2590
2591 bool
2471 SpectrogramLayer::paintDrawBuffer(View *v, 2592 SpectrogramLayer::paintDrawBuffer(View *v,
2472 int w, 2593 int w,
2473 int h, 2594 int h,
2474 int *binforx, 2595 int *binforx,
2475 int *binfory, 2596 int *binfory,
2510 2631
2511 for (int x = 0; x < w; ++x) { 2632 for (int x = 0; x < w; ++x) {
2512 2633
2513 if (binforx[x] < 0) continue; 2634 if (binforx[x] < 0) continue;
2514 2635
2515 float columnGain = m_gain; 2636 // float columnGain = m_gain;
2516 float columnMax = 0.f; 2637 float columnMax = 0.f;
2517 2638
2518 int sx0 = binforx[x] / divisor; 2639 int sx0 = binforx[x] / divisor;
2519 int sx1 = sx0; 2640 int sx1 = sx0;
2520 if (x+1 < w) sx1 = binforx[x+1] / divisor; 2641 if (x+1 < w) sx1 = binforx[x+1] / divisor;
2534 std::cerr << "Met unavailable column at col " << sx << std::endl; 2655 std::cerr << "Met unavailable column at col " << sx << std::endl;
2535 #endif 2656 #endif
2536 return false; 2657 return false;
2537 } 2658 }
2538 } 2659 }
2660
2661 MagnitudeRange mag;
2539 2662
2540 if (sx != psx) { 2663 if (sx != psx) {
2541 if (fft) { 2664 if (fft) {
2542 #ifdef DEBUG_SPECTROGRAM_REPAINT 2665 #ifdef DEBUG_SPECTROGRAM_REPAINT
2543 cerr << "Retrieving column " << sx << " from fft directly" << endl; 2666 cerr << "Retrieving column " << sx << " from fft directly" << endl;
2582 2705
2583 float value = 0.f; 2706 float value = 0.f;
2584 if (fft) value = values[sy - minbin]; 2707 if (fft) value = values[sy - minbin];
2585 else value = c[sy]; 2708 else value = c[sy];
2586 2709
2710 if (m_colourScale != PhaseColourScale) {
2711 if (!m_normalizeColumns) {
2712 value /= (m_fftSize/2.f);
2713 }
2714 mag.sample(value);
2715 value *= m_gain;
2716 }
2717
2587 /* 2718 /*
2588 if (m_colourScale != PhaseColourScale) { 2719 if (m_colourScale != PhaseColourScale) {
2589 if (!m_normalizeColumns) { 2720 if (!m_normalizeColumns) {
2590 value /= (m_fftSize/2.f); 2721 value /= (m_fftSize/2.f);
2591 } 2722 }
2598 // cerr <<x<<","<<y<<" -> "<<sx<<","<<sy<<" -> "<<values[sy]<<" -> "<<(int)pix<< endl; 2729 // cerr <<x<<","<<y<<" -> "<<sx<<","<<sy<<" -> "<<values[sy]<<" -> "<<(int)pix<< endl;
2599 */ 2730 */
2600 if (value > peaks[y]) peaks[y] = value; //!!! not right for phase! 2731 if (value > peaks[y]) peaks[y] = value; //!!! not right for phase!
2601 } 2732 }
2602 } 2733 }
2603 } 2734
2604 2735 if (mag.isSet()) {
2605 if (m_normalizeColumns && columnMax > 0.f) { 2736 if (sx >= int(m_columnMags.size())) {
2606 columnGain /= columnMax; 2737 std::cerr << "INTERNAL ERROR: " << sx << " >= "
2607 } 2738 << m_columnMags.size()
2739 << " at SpectrogramLayer.cpp::paintDrawBuffer"
2740 << std::endl;
2741 }
2742 m_columnMags[sx].sample(mag);
2743 }
2744 }
2745
2746 // if (m_normalizeColumns && columnMax > 0.f) {
2747 // columnGain /= columnMax;
2748 // }
2608 2749
2609 for (int y = 0; y < h; ++y) { 2750 for (int y = 0; y < h; ++y) {
2610 2751
2611 float peak = peaks[y]; 2752 float peak = peaks[y];
2612 2753
2613 if (m_colourScale != PhaseColourScale) { 2754 if (m_colourScale != PhaseColourScale &&
2614 if (!m_normalizeColumns) { 2755 m_normalizeColumns &&
2615 peak /= (m_fftSize/2.f); 2756 columnMax > 0.f) {
2616 } 2757 // if (!m_normalizeColumns) {
2758 // peak /= (m_fftSize/2.f);
2759 // }
2617 //!!! mag.sample(value); 2760 //!!! mag.sample(value);
2618 peak *= columnGain; 2761 peak /= columnMax;
2619 } 2762 }
2620 2763
2621 unsigned char peakpix = getDisplayValue(v, peak); 2764 unsigned char peakpix = getDisplayValue(v, peak);
2622 2765
2623 m_drawBuffer.setPixel(x, h-y-1, peakpix); 2766 m_drawBuffer.setPixel(x, h-y-1, peakpix);
2625 } 2768 }
2626 2769
2627 return true; 2770 return true;
2628 } 2771 }
2629 2772
2773 #ifdef NOT_DEFINED
2630 bool 2774 bool
2631 SpectrogramLayer::paintColumnValues(View *v, 2775 SpectrogramLayer::paintColumnValues(View *v,
2632 FFTModel *fft, 2776 FFTModel *fft,
2633 int x0, 2777 int x0,
2634 int x, 2778 int x,
2860 m_drawBuffer.setPixel(x, y, pixel); 3004 m_drawBuffer.setPixel(x, y, pixel);
2861 } 3005 }
2862 3006
2863 return true; 3007 return true;
2864 } 3008 }
2865 3009 #endif
2866 3010
2867 void 3011 void
2868 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const 3012 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const
2869 { 3013 {
2870 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); 3014 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures");