Mercurial > hg > svgui
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 |