Mercurial > hg > svgui
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"); |