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);