Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 719:67e6d518ac27
Bodge in Matthias's suggested normalise-to-log as an option in spectrogram and colour 3d plot layers (not wired into gui)
author | Chris Cannam |
---|---|
date | Tue, 28 Jan 2014 17:37:42 +0000 |
parents | 8072264dc61f |
children | 5d3a6ecdf2db 6a8d922f991d |
comparison
equal
deleted
inserted
replaced
704:b81f21f2c4c3 | 719:67e6d518ac27 |
---|---|
73 m_colourMap(0), | 73 m_colourMap(0), |
74 m_frequencyScale(LinearFrequencyScale), | 74 m_frequencyScale(LinearFrequencyScale), |
75 m_binDisplay(AllBins), | 75 m_binDisplay(AllBins), |
76 m_normalizeColumns(false), | 76 m_normalizeColumns(false), |
77 m_normalizeVisibleArea(false), | 77 m_normalizeVisibleArea(false), |
78 m_normalizeHybrid(false), | |
78 m_lastEmittedZoomStep(-1), | 79 m_lastEmittedZoomStep(-1), |
79 m_synchronous(false), | 80 m_synchronous(false), |
80 m_haveDetailedScale(false), | 81 m_haveDetailedScale(false), |
81 m_lastPaintBlockWidth(0), | 82 m_lastPaintBlockWidth(0), |
82 m_updateTimer(0), | 83 m_updateTimer(0), |
949 { | 950 { |
950 return m_normalizeColumns; | 951 return m_normalizeColumns; |
951 } | 952 } |
952 | 953 |
953 void | 954 void |
955 SpectrogramLayer::setNormalizeHybrid(bool n) | |
956 { | |
957 if (m_normalizeHybrid == n) return; | |
958 | |
959 invalidateImageCaches(); | |
960 invalidateMagnitudes(); | |
961 m_normalizeHybrid = n; | |
962 | |
963 emit layerParametersChanged(); | |
964 } | |
965 | |
966 bool | |
967 SpectrogramLayer::getNormalizeHybrid() const | |
968 { | |
969 return m_normalizeHybrid; | |
970 } | |
971 | |
972 void | |
954 SpectrogramLayer::setNormalizeVisibleArea(bool n) | 973 SpectrogramLayer::setNormalizeVisibleArea(bool n) |
955 { | 974 { |
956 SVDEBUG << "SpectrogramLayer::setNormalizeVisibleArea(" << n | 975 SVDEBUG << "SpectrogramLayer::setNormalizeVisibleArea(" << n |
957 << ") (from " << m_normalizeVisibleArea << ")" << endl; | 976 << ") (from " << m_normalizeVisibleArea << ")" << endl; |
958 | 977 |
1240 } | 1259 } |
1241 | 1260 |
1242 if (value > UCHAR_MAX) value = UCHAR_MAX; | 1261 if (value > UCHAR_MAX) value = UCHAR_MAX; |
1243 if (value < 0) value = 0; | 1262 if (value < 0) value = 0; |
1244 return value; | 1263 return value; |
1245 } | |
1246 | |
1247 float | |
1248 SpectrogramLayer::getInputForDisplayValue(unsigned char uc) const | |
1249 { | |
1250 //!!! unused | |
1251 | |
1252 int value = uc; | |
1253 float input; | |
1254 | |
1255 //!!! incorrect for normalizing visible area (and also out of date) | |
1256 | |
1257 switch (m_colourScale) { | |
1258 | |
1259 default: | |
1260 case LinearColourScale: | |
1261 input = float(value - 1) / 255.0 / (m_normalizeColumns ? 1 : 50); | |
1262 break; | |
1263 | |
1264 case MeterColourScale: | |
1265 input = AudioLevel::preview_to_multiplier(value - 1, 255) | |
1266 / (m_normalizeColumns ? 1.0 : 50.0); | |
1267 break; | |
1268 | |
1269 case dBSquaredColourScale: | |
1270 input = float(value - 1) / 255.0; | |
1271 input = (input * 80.0) - 80.0; | |
1272 input = powf(10.0, input) / 20.0; | |
1273 value = int(input); | |
1274 break; | |
1275 | |
1276 case dBColourScale: | |
1277 input = float(value - 1) / 255.0; | |
1278 input = (input * 80.0) - 80.0; | |
1279 input = powf(10.0, input) / 20.0; | |
1280 value = int(input); | |
1281 break; | |
1282 | |
1283 case PhaseColourScale: | |
1284 input = float(value - 128) * M_PI / 127.0; | |
1285 break; | |
1286 } | |
1287 | |
1288 return input; | |
1289 } | 1264 } |
1290 | 1265 |
1291 float | 1266 float |
1292 SpectrogramLayer::getEffectiveMinFrequency() const | 1267 SpectrogramLayer::getEffectiveMinFrequency() const |
1293 { | 1268 { |
2554 minbin, maxbin - 1); | 2529 minbin, maxbin - 1); |
2555 if (m_colourScale == PhaseColourScale) { | 2530 if (m_colourScale == PhaseColourScale) { |
2556 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); | 2531 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); |
2557 } else if (m_normalizeColumns) { | 2532 } else if (m_normalizeColumns) { |
2558 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); | 2533 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); |
2534 } else if (m_normalizeHybrid) { | |
2535 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); | |
2536 float max = fft->getMaximumMagnitudeAt(sx); | |
2537 if (max > 0.f) { | |
2538 for (int i = minbin; i <= maxbin; ++i) { | |
2539 values[i - minbin] *= log10(max); | |
2540 } | |
2541 } | |
2559 } else { | 2542 } else { |
2560 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); | 2543 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); |
2561 } | 2544 } |
2562 psx = sx; | 2545 psx = sx; |
2563 } | 2546 } |
2572 if (bin > maxbin) break; | 2555 if (bin > maxbin) break; |
2573 | 2556 |
2574 float value = values[bin - minbin]; | 2557 float value = values[bin - minbin]; |
2575 | 2558 |
2576 if (m_colourScale != PhaseColourScale) { | 2559 if (m_colourScale != PhaseColourScale) { |
2577 if (!m_normalizeColumns) { | 2560 if (!m_normalizeColumns && !m_normalizeHybrid) { |
2578 value /= (m_fftSize/2.f); | 2561 value /= (m_fftSize/2.f); |
2579 } | 2562 } |
2580 mag.sample(value); | 2563 mag.sample(value); |
2581 value *= m_gain; | 2564 value *= m_gain; |
2582 } | 2565 } |
2713 #endif | 2696 #endif |
2714 if (m_colourScale == PhaseColourScale) { | 2697 if (m_colourScale == PhaseColourScale) { |
2715 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2698 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2716 } else if (m_normalizeColumns) { | 2699 } else if (m_normalizeColumns) { |
2717 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2700 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2701 } else if (m_normalizeHybrid) { | |
2702 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | |
2703 float max = fft->getMaximumMagnitudeAt(sx); | |
2704 for (int i = minbin; i <= maxbin; ++i) { | |
2705 if (max > 0.f) { | |
2706 autoarray[i - minbin] *= log10(max); | |
2707 } | |
2708 } | |
2718 } else { | 2709 } else { |
2719 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2710 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2720 } | 2711 } |
2721 } else { | 2712 } else { |
2722 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2713 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2723 SVDEBUG << "Retrieving column " << sx << " from peaks cache" << endl; | 2714 SVDEBUG << "Retrieving column " << sx << " from peaks cache" << endl; |
2724 #endif | 2715 #endif |
2725 c = sourceModel->getColumn(sx); | 2716 c = sourceModel->getColumn(sx); |
2726 if (m_normalizeColumns) { | 2717 if (m_normalizeColumns || m_normalizeHybrid) { |
2727 for (int y = 0; y < h; ++y) { | 2718 for (int y = 0; y < h; ++y) { |
2728 if (c[y] > columnMax) columnMax = c[y]; | 2719 if (c[y] > columnMax) columnMax = c[y]; |
2729 } | 2720 } |
2730 } | 2721 } |
2731 values = c.constData() + minbin; | 2722 values = c.constData() + minbin; |
2821 for (int y = 0; y < h; ++y) { | 2812 for (int y = 0; y < h; ++y) { |
2822 | 2813 |
2823 float peak = peaks[y]; | 2814 float peak = peaks[y]; |
2824 | 2815 |
2825 if (m_colourScale != PhaseColourScale && | 2816 if (m_colourScale != PhaseColourScale && |
2826 m_normalizeColumns && | 2817 (m_normalizeColumns || m_normalizeHybrid) && |
2827 columnMax > 0.f) { | 2818 columnMax > 0.f) { |
2828 peak /= columnMax; | 2819 peak /= columnMax; |
2820 if (m_normalizeHybrid) { | |
2821 peak *= log10(columnMax); | |
2822 } | |
2829 } | 2823 } |
2830 | 2824 |
2831 unsigned char peakpix = getDisplayValue(v, peak); | 2825 unsigned char peakpix = getDisplayValue(v, peak); |
2832 | 2826 |
2833 m_drawBuffer.setPixel(x, h-y-1, peakpix); | 2827 m_drawBuffer.setPixel(x, h-y-1, peakpix); |