comparison layer/SpectrogramLayer.cpp @ 1092:9b826dd23c84 spectrogram-minor-refactor

Colour scales (partly)
author Chris Cannam
date Thu, 07 Jul 2016 12:39:56 +0100
parents ac10a087e045
children cd22f74dc159
comparison
equal deleted inserted replaced
1091:ac10a087e045 1092:9b826dd23c84
70 m_colourRotation(0), 70 m_colourRotation(0),
71 m_initialRotation(0), 71 m_initialRotation(0),
72 m_minFrequency(10), 72 m_minFrequency(10),
73 m_maxFrequency(8000), 73 m_maxFrequency(8000),
74 m_initialMaxFrequency(8000), 74 m_initialMaxFrequency(8000),
75 m_colourScale(dBColourScale), 75 m_colourScale(ColourScale::LogColourScale),
76 m_colourMap(0), 76 m_colourMap(0),
77 m_frequencyScale(LinearFrequencyScale), 77 m_frequencyScale(LinearFrequencyScale),
78 m_binDisplay(AllBins), 78 m_binDisplay(AllBins),
79 m_normalization(ColumnOp::NoNormalization), 79 m_normalization(ColumnOp::NoNormalization),
80 m_lastEmittedZoomStep(-1), 80 m_lastEmittedZoomStep(-1),
95 setWindowSize(8192); 95 setWindowSize(8192);
96 setWindowHopLevel(4); 96 setWindowHopLevel(4);
97 m_initialMaxFrequency = 1500; 97 m_initialMaxFrequency = 1500;
98 setMaxFrequency(1500); 98 setMaxFrequency(1500);
99 setMinFrequency(40); 99 setMinFrequency(40);
100 setColourScale(LinearColourScale); 100 setColourScale(ColourScale::LinearColourScale);
101 setColourMap(ColourMapper::Sunset); 101 setColourMap(ColourMapper::Sunset);
102 setFrequencyScale(LogFrequencyScale); 102 setFrequencyScale(LogFrequencyScale);
103 colourConfigName = "spectrogram-melodic-colour"; 103 colourConfigName = "spectrogram-melodic-colour";
104 colourConfigDefault = int(ColourMapper::Sunset); 104 colourConfigDefault = int(ColourMapper::Sunset);
105 // setGain(20); 105 // setGain(20);
108 setWindowHopLevel(5); 108 setWindowHopLevel(5);
109 m_initialMaxFrequency = 2000; 109 m_initialMaxFrequency = 2000;
110 setMaxFrequency(2000); 110 setMaxFrequency(2000);
111 setMinFrequency(40); 111 setMinFrequency(40);
112 setFrequencyScale(LogFrequencyScale); 112 setFrequencyScale(LogFrequencyScale);
113 setColourScale(LinearColourScale); 113 setColourScale(ColourScale::LinearColourScale);
114 setBinDisplay(PeakFrequencies); 114 setBinDisplay(PeakFrequencies);
115 setNormalization(ColumnOp::NormalizeColumns); 115 setNormalization(ColumnOp::NormalizeColumns);
116 colourConfigName = "spectrogram-melodic-colour"; 116 colourConfigName = "spectrogram-melodic-colour";
117 colourConfigDefault = int(ColourMapper::Sunset); 117 colourConfigDefault = int(ColourMapper::Sunset);
118 } 118 }
271 271
272 } else if (name == "Colour Scale") { 272 } else if (name == "Colour Scale") {
273 273
274 *min = 0; 274 *min = 0;
275 *max = 4; 275 *max = 4;
276 *deflt = int(dBColourScale); 276 *deflt = 2;
277 277
278 val = (int)m_colourScale; 278 val = (int)m_colourScale;
279 279
280 } else if (name == "Colour") { 280 } else if (name == "Colour") {
281 281
534 m_lastEmittedZoomStep = vs; 534 m_lastEmittedZoomStep = vs;
535 } 535 }
536 } else if (name == "Colour Scale") { 536 } else if (name == "Colour Scale") {
537 switch (value) { 537 switch (value) {
538 default: 538 default:
539 case 0: setColourScale(LinearColourScale); break; 539 case 0: setColourScale(ColourScale::LinearColourScale); break;
540 case 1: setColourScale(MeterColourScale); break; 540 case 1: setColourScale(ColourScale::MeterColourScale); break;
541 case 2: setColourScale(dBSquaredColourScale); break; 541 case 2: setColourScale(ColourScale::LogColourScale); break; //!!! dB^2
542 case 3: setColourScale(dBColourScale); break; 542 case 3: setColourScale(ColourScale::LogColourScale); break;
543 case 4: setColourScale(PhaseColourScale); break; 543 case 4: setColourScale(ColourScale::PhaseColourScale); break;
544 } 544 }
545 } else if (name == "Frequency Scale") { 545 } else if (name == "Frequency Scale") {
546 switch (value) { 546 switch (value) {
547 default: 547 default:
548 case 0: setFrequencyScale(LinearFrequencyScale); break; 548 case 0: setFrequencyScale(LinearFrequencyScale); break;
811 811
812 emit layerParametersChanged(); 812 emit layerParametersChanged();
813 } 813 }
814 814
815 void 815 void
816 SpectrogramLayer::setColourScale(ColourScale colourScale) 816 SpectrogramLayer::setColourScale(ColourScale::Scale colourScale)
817 { 817 {
818 if (m_colourScale == colourScale) return; 818 if (m_colourScale == colourScale) return;
819 819
820 invalidateImageCaches(); 820 invalidateImageCaches();
821 821
822 m_colourScale = colourScale; 822 m_colourScale = colourScale;
823 823
824 emit layerParametersChanged(); 824 emit layerParametersChanged();
825 } 825 }
826 826
827 SpectrogramLayer::ColourScale 827 ColourScale::Scale
828 SpectrogramLayer::getColourScale() const 828 SpectrogramLayer::getColourScale() const
829 { 829 {
830 return m_colourScale; 830 return m_colourScale;
831 } 831 }
832 832
1021 } 1021 }
1022 1022
1023 unsigned char 1023 unsigned char
1024 SpectrogramLayer::getDisplayValue(LayerGeometryProvider *v, double input) const 1024 SpectrogramLayer::getDisplayValue(LayerGeometryProvider *v, double input) const
1025 { 1025 {
1026 int value; 1026 int value = 0;
1027 1027
1028 double min = 0.0; 1028 double min = 0.0;
1029 double max = 1.0; 1029 double max = 1.0;
1030 1030
1031 if (m_normalization == ColumnOp::NormalizeVisibleArea) { 1031 if (m_normalization == ColumnOp::NormalizeVisibleArea) {
1032 min = m_viewMags[v->getId()].getMin(); 1032 min = m_viewMags[v->getId()].getMin();
1033 max = m_viewMags[v->getId()].getMax(); 1033 max = m_viewMags[v->getId()].getMax();
1034 } else if (m_normalization != ColumnOp::NormalizeColumns) { 1034 } else if (m_normalization != ColumnOp::NormalizeColumns) {
1035 if (m_colourScale == LinearColourScale //|| 1035 if (m_colourScale == ColourScale::LinearColourScale //||
1036 // m_colourScale == MeterColourScale) { 1036 // m_colourScale == MeterColourScale) {
1037 ) { 1037 ) {
1038 max = 0.1; 1038 max = 0.1;
1039 } 1039 }
1040 } 1040 }
1044 if (max == 0.0) max = 1.0; 1044 if (max == 0.0) max = 1.0;
1045 if (max == min) min = max - 0.0001; 1045 if (max == min) min = max - 0.0001;
1046 1046
1047 switch (m_colourScale) { 1047 switch (m_colourScale) {
1048 1048
1049 default: 1049 case ColourScale::LinearColourScale:
1050 case LinearColourScale:
1051 value = int(((input - min) / (max - min)) * 255.0) + 1; 1050 value = int(((input - min) / (max - min)) * 255.0) + 1;
1052 break; 1051 break;
1053 1052
1054 case MeterColourScale: 1053 case ColourScale::MeterColourScale:
1055 value = AudioLevel::multiplier_to_preview 1054 value = AudioLevel::multiplier_to_preview
1056 ((input - min) / (max - min), 254) + 1; 1055 ((input - min) / (max - min), 254) + 1;
1057 break; 1056 break;
1058 1057
1059 case dBSquaredColourScale: 1058 //!!! check this
1059 /* case dBSquaredColourScale:
1060 input = ((input - min) * (input - min)) / ((max - min) * (max - min)); 1060 input = ((input - min) * (input - min)) / ((max - min) * (max - min));
1061 if (input > 0.0) { 1061 if (input > 0.0) {
1062 input = 10.0 * log10(input); 1062 input = 10.0 * log10(input);
1063 } else { 1063 } else {
1064 input = thresh; 1064 input = thresh;
1070 input = (input - thresh) / (-thresh); 1070 input = (input - thresh) / (-thresh);
1071 if (input < 0.0) input = 0.0; 1071 if (input < 0.0) input = 0.0;
1072 if (input > 1.0) input = 1.0; 1072 if (input > 1.0) input = 1.0;
1073 value = int(input * 255.0) + 1; 1073 value = int(input * 255.0) + 1;
1074 break; 1074 break;
1075 1075 */
1076 case dBColourScale: 1076 case ColourScale::LogColourScale:
1077 //!!! experiment with normalizing the visible area this way. 1077 //!!! experiment with normalizing the visible area this way.
1078 //In any case, we need to have some indication of what the dB 1078 //In any case, we need to have some indication of what the dB
1079 //scale is relative to. 1079 //scale is relative to.
1080 input = (input - min) / (max - min); 1080 input = (input - min) / (max - min);
1081 if (input > 0.0) { 1081 if (input > 0.0) {
1091 if (input < 0.0) input = 0.0; 1091 if (input < 0.0) input = 0.0;
1092 if (input > 1.0) input = 1.0; 1092 if (input > 1.0) input = 1.0;
1093 value = int(input * 255.0) + 1; 1093 value = int(input * 255.0) + 1;
1094 break; 1094 break;
1095 1095
1096 case PhaseColourScale: 1096 case ColourScale::PhaseColourScale:
1097 value = int((input * 127.0 / M_PI) + 128); 1097 value = int((input * 127.0 / M_PI) + 128);
1098 break; 1098 break;
1099
1100 case ColourScale::PlusMinusOneScale:
1101 case ColourScale::AbsoluteScale:
1102 default:
1103 ;
1099 } 1104 }
1100 1105
1101 if (value > UCHAR_MAX) value = UCHAR_MAX; 1106 if (value > UCHAR_MAX) value = UCHAR_MAX;
1102 if (value < 0) value = 0; 1107 if (value < 0) value = 0;
1103 return (unsigned char)value; 1108 return (unsigned char)value;
1594 sources.verticalBinLayer = this; 1599 sources.verticalBinLayer = this;
1595 sources.fft = getFFTModel(); 1600 sources.fft = getFFTModel();
1596 sources.source = sources.fft; 1601 sources.source = sources.fft;
1597 sources.peaks = getPeakCache(); 1602 sources.peaks = getPeakCache();
1598 1603
1599 ::ColourScale::Parameters cparams; 1604 ColourScale::Parameters cparams;
1600 //!!! todo 1605 cparams.colourMap = m_colourMap;
1606 cparams.scale = m_colourScale;
1601 1607
1602 Colour3DPlotRenderer::Parameters params; 1608 Colour3DPlotRenderer::Parameters params;
1603 params.colourScale = ::ColourScale(cparams); 1609 params.colourScale = ColourScale(cparams);
1604 params.normalization = m_normalization; 1610 params.normalization = m_normalization;
1605 //!!! map properly: 1611 //!!! map properly:
1606 params.binDisplay = (Colour3DPlotRenderer::BinDisplay)(int)m_binDisplay; 1612 params.binDisplay = (Colour3DPlotRenderer::BinDisplay)(int)m_binDisplay;
1607 params.binScale = (Colour3DPlotRenderer::BinScale)(int)m_frequencyScale; 1613 params.binScale = (Colour3DPlotRenderer::BinScale)(int)m_frequencyScale;
1608 //!!! and the rest 1614 //!!! and the rest
1913 } 1919 }
1914 if (m_drawBuffer.width() < bufwid || m_drawBuffer.height() != h) { 1920 if (m_drawBuffer.width() < bufwid || m_drawBuffer.height() != h) {
1915 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); 1921 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8);
1916 } 1922 }
1917 usePeaksCache = (increment * m_peakCacheDivisor) < zoomLevel; 1923 usePeaksCache = (increment * m_peakCacheDivisor) < zoomLevel;
1918 if (m_colourScale == PhaseColourScale) usePeaksCache = false; 1924 if (m_colourScale == ColourScale::PhaseColourScale) usePeaksCache = false;
1919 } 1925 }
1920 1926
1921 for (int pixel = 0; pixel < 256; ++pixel) { 1927 for (int pixel = 0; pixel < 256; ++pixel) {
1922 m_drawBuffer.setColor((unsigned char)pixel, 1928 m_drawBuffer.setColor((unsigned char)pixel,
1923 m_palette.getColour((unsigned char)pixel).rgb()); 1929 m_palette.getColour((unsigned char)pixel).rgb());
2243 column = getColumnFromFFTModel(fft, 2249 column = getColumnFromFFTModel(fft,
2244 sx, 2250 sx,
2245 minbin, 2251 minbin,
2246 maxbin - minbin + 1); 2252 maxbin - minbin + 1);
2247 2253
2248 if (m_colourScale != PhaseColourScale) { 2254 if (m_colourScale != ColourScale::PhaseColourScale) {
2249 column = ColumnOp::fftScale(column, getFFTSize()); 2255 column = ColumnOp::fftScale(column, getFFTSize());
2250 } 2256 }
2251 2257
2252 recordColumnExtents(column, 2258 recordColumnExtents(column,
2253 sx, 2259 sx,
2254 overallMag, 2260 overallMag,
2255 overallMagChanged); 2261 overallMagChanged);
2256 2262
2257 if (m_colourScale != PhaseColourScale) { 2263 if (m_colourScale != ColourScale::PhaseColourScale) {
2258 column = ColumnOp::normalize(column, m_normalization); 2264 column = ColumnOp::normalize(column, m_normalization);
2259 } 2265 }
2260 2266
2261 preparedColumn = ColumnOp::applyGain(column, m_gain); 2267 preparedColumn = ColumnOp::applyGain(column, m_gain);
2262 2268
2335 int minbin, 2341 int minbin,
2336 int bincount) const 2342 int bincount) const
2337 { 2343 {
2338 vector<float> values(bincount, 0.f); 2344 vector<float> values(bincount, 0.f);
2339 2345
2340 if (m_colourScale == PhaseColourScale) { 2346 if (m_colourScale == ColourScale::PhaseColourScale) {
2341 fft->getPhasesAt(sx, values.data(), minbin, bincount); 2347 fft->getPhasesAt(sx, values.data(), minbin, bincount);
2342 } else { 2348 } else {
2343 fft->getMagnitudesAt(sx, values.data(), minbin, bincount); 2349 fft->getMagnitudesAt(sx, values.data(), minbin, bincount);
2344 } 2350 }
2345 2351
2350 SpectrogramLayer::getColumnFromGenericModel(DenseThreeDimensionalModel *model, 2356 SpectrogramLayer::getColumnFromGenericModel(DenseThreeDimensionalModel *model,
2351 int sx, // column number in model 2357 int sx, // column number in model
2352 int minbin, 2358 int minbin,
2353 int bincount) const 2359 int bincount) const
2354 { 2360 {
2355 if (m_colourScale == PhaseColourScale) { 2361 if (m_colourScale == ColourScale::PhaseColourScale) {
2356 throw std::logic_error("can't use phase scale with generic 3d model"); 2362 throw std::logic_error("can't use phase scale with generic 3d model");
2357 } 2363 }
2358 2364
2359 auto col = model->getColumn(sx); 2365 auto col = model->getColumn(sx);
2360 2366
2504 sx, 2510 sx,
2505 minbin, 2511 minbin,
2506 maxbin - minbin + 1); 2512 maxbin - minbin + 1);
2507 } 2513 }
2508 2514
2509 if (m_colourScale != PhaseColourScale) { 2515 if (m_colourScale != ColourScale::PhaseColourScale) {
2510 column = ColumnOp::fftScale(column, getFFTSize()); 2516 column = ColumnOp::fftScale(column, getFFTSize());
2511 } 2517 }
2512 2518
2513 recordColumnExtents(column, 2519 recordColumnExtents(column,
2514 sx, 2520 sx,
2515 overallMag, 2521 overallMag,
2516 overallMagChanged); 2522 overallMagChanged);
2517 2523
2518 if (m_colourScale != PhaseColourScale) { 2524 if (m_colourScale != ColourScale::PhaseColourScale) {
2519 column = ColumnOp::normalize(column, m_normalization); 2525 column = ColumnOp::normalize(column, m_normalization);
2520 } 2526 }
2521 2527
2522 if (m_binDisplay == PeakBins) { 2528 if (m_binDisplay == PeakBins) {
2523 column = ColumnOp::peakPick(column); 2529 column = ColumnOp::peakPick(column);
3062 int toff = -textHeight + paint.fontMetrics().ascent() + 2; 3068 int toff = -textHeight + paint.fontMetrics().ascent() + 2;
3063 3069
3064 if (detailed && (h > textHeight * 3 + 10)) { 3070 if (detailed && (h > textHeight * 3 + 10)) {
3065 3071
3066 int topLines = 2; 3072 int topLines = 2;
3067 if (m_colourScale == PhaseColourScale) topLines = 1; 3073 if (m_colourScale == ColourScale::PhaseColourScale) topLines = 1;
3068 3074
3069 int ch = h - textHeight * (topLines + 1) - 8; 3075 int ch = h - textHeight * (topLines + 1) - 8;
3070 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 3076 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
3071 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); 3077 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
3072 3078
3089 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f; 3095 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f;
3090 bottom = QString("%1").arg(lrint(dBmin)); 3096 bottom = QString("%1").arg(lrint(dBmin));
3091 3097
3092 //!!! & phase etc 3098 //!!! & phase etc
3093 3099
3094 if (m_colourScale != PhaseColourScale) { 3100 if (m_colourScale != ColourScale::PhaseColourScale) {
3095 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2, 3101 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
3096 2 + textHeight + toff, "dBFS"); 3102 2 + textHeight + toff, "dBFS");
3097 } 3103 }
3098 3104
3099 // paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2, 3105 // paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2,
3390 } 3396 }
3391 // SVDEBUG << "SpectrogramLayer::setMeasureRectYCoord: start " << r.startY << " <- " << y << ", end " << r.endY << " <- " << y << endl; 3397 // SVDEBUG << "SpectrogramLayer::setMeasureRectYCoord: start " << r.startY << " <- " << y << ", end " << r.endY << " <- " << y << endl;
3392 3398
3393 } 3399 }
3394 3400
3401 static ColourScale::Scale
3402 convertInColourScale(int fileScale)
3403 {
3404 switch (fileScale) {
3405 case 0: return ColourScale::LinearColourScale;
3406 case 1: return ColourScale::MeterColourScale;
3407 case 2: return ColourScale::LogColourScale; //!!!
3408 case 3: return ColourScale::LogColourScale;
3409 case 4: return ColourScale::PhaseColourScale;
3410 default: return ColourScale::LinearColourScale;
3411 }
3412 }
3413
3414 static int
3415 convertOutColourScale(ColourScale::Scale scale)
3416 {
3417 switch (scale) {
3418 case ColourScale::LinearColourScale: return 0;
3419 case ColourScale::MeterColourScale: return 1;
3420 case ColourScale::LogColourScale: return 3; //!!!
3421 case ColourScale::PhaseColourScale: return 4;
3422 case ColourScale::PlusMinusOneScale:
3423 case ColourScale::AbsoluteScale:
3424 default: return 0;
3425 }
3426 }
3427
3395 void 3428 void
3396 SpectrogramLayer::toXml(QTextStream &stream, 3429 SpectrogramLayer::toXml(QTextStream &stream,
3397 QString indent, QString extraAttributes) const 3430 QString indent, QString extraAttributes) const
3398 { 3431 {
3399 QString s; 3432 QString s;
3416 "colourRotation=\"%5\" " 3449 "colourRotation=\"%5\" "
3417 "frequencyScale=\"%6\" " 3450 "frequencyScale=\"%6\" "
3418 "binDisplay=\"%7\" ") 3451 "binDisplay=\"%7\" ")
3419 .arg(m_minFrequency) 3452 .arg(m_minFrequency)
3420 .arg(m_maxFrequency) 3453 .arg(m_maxFrequency)
3421 .arg(m_colourScale) 3454 .arg(convertOutColourScale(m_colourScale))
3422 .arg(m_colourMap) 3455 .arg(m_colourMap)
3423 .arg(m_colourRotation) 3456 .arg(m_colourRotation)
3424 .arg(m_frequencyScale) 3457 .arg(m_frequencyScale)
3425 .arg(m_binDisplay); 3458 .arg(m_binDisplay);
3426 3459
3491 if (ok) { 3524 if (ok) {
3492 SVDEBUG << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << endl; 3525 SVDEBUG << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << endl;
3493 setMaxFrequency(maxFrequency); 3526 setMaxFrequency(maxFrequency);
3494 } 3527 }
3495 3528
3496 ColourScale colourScale = (ColourScale) 3529 ColourScale::Scale colourScale = convertInColourScale
3497 attributes.value("colourScale").toInt(&ok); 3530 (attributes.value("colourScale").toInt(&ok));
3498 if (ok) setColourScale(colourScale); 3531 if (ok) setColourScale(colourScale);
3499 3532
3500 int colourMap = attributes.value("colourScheme").toInt(&ok); 3533 int colourMap = attributes.value("colourScheme").toInt(&ok);
3501 if (ok) setColourMap(colourMap); 3534 if (ok) setColourMap(colourMap);
3502 3535