Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 1104:46cc4644206d spectrogram-minor-refactor
Convert ColumnNormalization to an enum class, and separate out normalize-visible
author | Chris Cannam |
---|---|
date | Thu, 14 Jul 2016 16:12:05 +0100 |
parents | d84a0033b305 |
children | ea5ae9dd10ba |
comparison
equal
deleted
inserted
replaced
1103:d84a0033b305 | 1104:46cc4644206d |
---|---|
74 m_initialMaxFrequency(8000), | 74 m_initialMaxFrequency(8000), |
75 m_colourScale(ColourScale::LogColourScale), | 75 m_colourScale(ColourScale::LogColourScale), |
76 m_colourMap(0), | 76 m_colourMap(0), |
77 m_binScale(BinScale::Linear), | 77 m_binScale(BinScale::Linear), |
78 m_binDisplay(BinDisplay::AllBins), | 78 m_binDisplay(BinDisplay::AllBins), |
79 m_normalization(ColumnOp::NoNormalization), | 79 m_normalization(ColumnNormalization::None), |
80 m_normalizeVisibleArea(false), | |
80 m_lastEmittedZoomStep(-1), | 81 m_lastEmittedZoomStep(-1), |
81 m_synchronous(false), | 82 m_synchronous(false), |
82 m_haveDetailedScale(false), | 83 m_haveDetailedScale(false), |
83 m_exiting(false), | 84 m_exiting(false), |
84 m_fftModel(0), | 85 m_fftModel(0), |
110 setMaxFrequency(2000); | 111 setMaxFrequency(2000); |
111 setMinFrequency(40); | 112 setMinFrequency(40); |
112 setBinScale(BinScale::Log); | 113 setBinScale(BinScale::Log); |
113 setColourScale(ColourScale::LinearColourScale); | 114 setColourScale(ColourScale::LinearColourScale); |
114 setBinDisplay(BinDisplay::PeakFrequencies); | 115 setBinDisplay(BinDisplay::PeakFrequencies); |
115 setNormalization(ColumnOp::NormalizeColumns); | 116 setNormalization(ColumnNormalization::Max1); |
116 colourConfigName = "spectrogram-melodic-colour"; | 117 colourConfigName = "spectrogram-melodic-colour"; |
117 colourConfigDefault = int(ColourMapper::Sunset); | 118 colourConfigDefault = int(ColourMapper::Sunset); |
118 } | 119 } |
119 | 120 |
120 QSettings settings; | 121 QSettings settings; |
132 | 133 |
133 SpectrogramLayer::~SpectrogramLayer() | 134 SpectrogramLayer::~SpectrogramLayer() |
134 { | 135 { |
135 invalidateImageCaches(); | 136 invalidateImageCaches(); |
136 invalidateFFTModel(); | 137 invalidateFFTModel(); |
138 } | |
139 | |
140 ColourScale::Scale | |
141 SpectrogramLayer::convertToColourScale(int value) | |
142 { | |
143 switch (value) { | |
144 case 0: return ColourScale::LinearColourScale; | |
145 case 1: return ColourScale::MeterColourScale; | |
146 case 2: return ColourScale::LogColourScale; //!!! db^2 | |
147 case 3: return ColourScale::LogColourScale; | |
148 case 4: return ColourScale::PhaseColourScale; | |
149 default: return ColourScale::LinearColourScale; | |
150 } | |
151 } | |
152 | |
153 int | |
154 SpectrogramLayer::convertFromColourScale(ColourScale::Scale scale) | |
155 { | |
156 switch (scale) { | |
157 case ColourScale::LinearColourScale: return 0; | |
158 case ColourScale::MeterColourScale: return 1; | |
159 case ColourScale::LogColourScale: return 3; //!!! + db^2 | |
160 case ColourScale::PhaseColourScale: return 4; | |
161 | |
162 case ColourScale::PlusMinusOneScale: | |
163 case ColourScale::AbsoluteScale: | |
164 default: return 0; | |
165 } | |
166 } | |
167 | |
168 std::pair<ColumnNormalization, bool> | |
169 SpectrogramLayer::convertToColumnNorm(int value) | |
170 { | |
171 switch (value) { | |
172 default: | |
173 case 0: return { ColumnNormalization::None, false }; | |
174 case 1: return { ColumnNormalization::Max1, false }; | |
175 case 2: return { ColumnNormalization::None, true }; // visible area | |
176 case 3: return { ColumnNormalization::Hybrid, false }; | |
177 } | |
178 } | |
179 | |
180 int | |
181 SpectrogramLayer::convertFromColumnNorm(ColumnNormalization norm, bool visible) | |
182 { | |
183 if (visible) return 2; | |
184 switch (norm) { | |
185 case ColumnNormalization::None: return 0; | |
186 case ColumnNormalization::Max1: return 1; | |
187 case ColumnNormalization::Hybrid: return 3; | |
188 | |
189 case ColumnNormalization::Sum1: | |
190 default: return 0; | |
191 } | |
137 } | 192 } |
138 | 193 |
139 void | 194 void |
140 SpectrogramLayer::setModel(const DenseTimeValueModel *model) | 195 SpectrogramLayer::setModel(const DenseTimeValueModel *model) |
141 { | 196 { |
275 // linear, meter, db^2, db, phase | 330 // linear, meter, db^2, db, phase |
276 *min = 0; | 331 *min = 0; |
277 *max = 4; | 332 *max = 4; |
278 *deflt = 2; | 333 *deflt = 2; |
279 | 334 |
280 val = (int)m_colourScale; | 335 val = convertFromColourScale(m_colourScale); |
281 | 336 |
282 } else if (name == "Colour") { | 337 } else if (name == "Colour") { |
283 | 338 |
284 *min = 0; | 339 *min = 0; |
285 *max = ColourMapper::getColourMapCount() - 1; | 340 *max = ColourMapper::getColourMapCount() - 1; |
359 | 414 |
360 } else if (name == "Normalization") { | 415 } else if (name == "Normalization") { |
361 | 416 |
362 *min = 0; | 417 *min = 0; |
363 *max = 3; | 418 *max = 3; |
364 *deflt = int(ColumnOp::NoNormalization); | 419 *deflt = 0; |
365 val = (int)m_normalization; | 420 |
421 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); | |
366 | 422 |
367 } else { | 423 } else { |
368 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | 424 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); |
369 } | 425 } |
370 | 426 |
556 case 0: setBinDisplay(BinDisplay::AllBins); break; | 612 case 0: setBinDisplay(BinDisplay::AllBins); break; |
557 case 1: setBinDisplay(BinDisplay::PeakBins); break; | 613 case 1: setBinDisplay(BinDisplay::PeakBins); break; |
558 case 2: setBinDisplay(BinDisplay::PeakFrequencies); break; | 614 case 2: setBinDisplay(BinDisplay::PeakFrequencies); break; |
559 } | 615 } |
560 } else if (name == "Normalization") { | 616 } else if (name == "Normalization") { |
561 switch (value) { | 617 auto n = convertToColumnNorm(value); |
562 default: | 618 setNormalization(n.first); |
563 case 0: setNormalization(ColumnOp::NoNormalization); break; | 619 setNormalizeVisibleArea(n.second); |
564 case 1: setNormalization(ColumnOp::NormalizeColumns); break; | |
565 case 2: setNormalization(ColumnOp::NormalizeVisibleArea); break; | |
566 case 3: setNormalization(ColumnOp::NormalizeHybrid); break; | |
567 } | |
568 } | 620 } |
569 } | 621 } |
570 | 622 |
571 void | 623 void |
572 SpectrogramLayer::invalidateImageCaches() | 624 SpectrogramLayer::invalidateImageCaches() |
884 { | 936 { |
885 return m_binDisplay; | 937 return m_binDisplay; |
886 } | 938 } |
887 | 939 |
888 void | 940 void |
889 SpectrogramLayer::setNormalization(ColumnOp::Normalization n) | 941 SpectrogramLayer::setNormalization(ColumnNormalization n) |
890 { | 942 { |
891 if (m_normalization == n) return; | 943 if (m_normalization == n) return; |
892 | 944 |
893 invalidateImageCaches(); | 945 invalidateImageCaches(); |
894 invalidateMagnitudes(); | 946 invalidateMagnitudes(); |
895 m_normalization = n; | 947 m_normalization = n; |
896 | 948 |
897 emit layerParametersChanged(); | 949 emit layerParametersChanged(); |
898 } | 950 } |
899 | 951 |
900 ColumnOp::Normalization | 952 ColumnNormalization |
901 SpectrogramLayer::getNormalization() const | 953 SpectrogramLayer::getNormalization() const |
902 { | 954 { |
903 return m_normalization; | 955 return m_normalization; |
956 } | |
957 | |
958 void | |
959 SpectrogramLayer::setNormalizeVisibleArea(bool n) | |
960 { | |
961 if (m_normalizeVisibleArea == n) return; | |
962 | |
963 invalidateImageCaches(); | |
964 invalidateMagnitudes(); | |
965 m_normalizeVisibleArea = n; | |
966 | |
967 emit layerParametersChanged(); | |
968 } | |
969 | |
970 bool | |
971 SpectrogramLayer::getNormalizeVisibleArea() const | |
972 { | |
973 return m_normalizeVisibleArea; | |
904 } | 974 } |
905 | 975 |
906 void | 976 void |
907 SpectrogramLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant) | 977 SpectrogramLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant) |
908 { | 978 { |
1028 int value = 0; | 1098 int value = 0; |
1029 | 1099 |
1030 double min = 0.0; | 1100 double min = 0.0; |
1031 double max = 1.0; | 1101 double max = 1.0; |
1032 | 1102 |
1033 if (m_normalization == ColumnOp::NormalizeVisibleArea) { | 1103 if (m_normalizeVisibleArea) { |
1034 min = m_viewMags[v->getId()].getMin(); | 1104 min = m_viewMags[v->getId()].getMin(); |
1035 max = m_viewMags[v->getId()].getMax(); | 1105 max = m_viewMags[v->getId()].getMax(); |
1036 } else if (m_normalization != ColumnOp::NormalizeColumns) { | 1106 } else if (m_normalization != ColumnNormalization::Max1) { |
1037 if (m_colourScale == ColourScale::LinearColourScale //|| | 1107 if (m_colourScale == ColourScale::LinearColourScale //|| |
1038 // m_colourScale == MeterColourScale) { | 1108 // m_colourScale == MeterColourScale) { |
1039 ) { | 1109 ) { |
1040 max = 0.1; | 1110 max = 0.1; |
1041 } | 1111 } |
1585 cparams.scale = m_colourScale; | 1655 cparams.scale = m_colourScale; |
1586 cparams.threshold = m_threshold; | 1656 cparams.threshold = m_threshold; |
1587 cparams.gain = m_gain; | 1657 cparams.gain = m_gain; |
1588 | 1658 |
1589 if (m_colourScale != ColourScale::PhaseColourScale && | 1659 if (m_colourScale != ColourScale::PhaseColourScale && |
1590 m_normalization == ColumnOp::NoNormalization) { | 1660 m_normalization == ColumnNormalization::None) { |
1591 cparams.gain *= 2.f / float(getFFTSize()); | 1661 cparams.gain *= 2.f / float(getFFTSize()); |
1592 } | 1662 } |
1593 | 1663 |
1594 Colour3DPlotRenderer::Parameters params; | 1664 Colour3DPlotRenderer::Parameters params; |
1595 params.colourScale = ColourScale(cparams); | 1665 params.colourScale = ColourScale(cparams); |
1666 | 1736 |
1667 if (updateViewMagnitudes(v)) { | 1737 if (updateViewMagnitudes(v)) { |
1668 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1738 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1669 cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v->getId()].getMin() << "->" << m_viewMags[v->getId()].getMax() << "]" << endl; | 1739 cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v->getId()].getMin() << "->" << m_viewMags[v->getId()].getMax() << "]" << endl; |
1670 #endif | 1740 #endif |
1671 if (m_normalization == ColumnOp::NormalizeVisibleArea) { | 1741 if (m_normalizeVisibleArea) { |
1672 cache.invalidate(); | 1742 cache.invalidate(); |
1673 } | 1743 } |
1674 } | 1744 } |
1675 | 1745 |
1676 if (cache.getZoomLevel() != zoomLevel || | 1746 if (cache.getZoomLevel() != zoomLevel || |
2107 paint.drawImage(pr.x(), pr.y(), cache.getImage(), | 2177 paint.drawImage(pr.x(), pr.y(), cache.getImage(), |
2108 pr.x(), pr.y(), pr.width(), pr.height()); | 2178 pr.x(), pr.y(), pr.width(), pr.height()); |
2109 | 2179 |
2110 if (!m_synchronous) { | 2180 if (!m_synchronous) { |
2111 | 2181 |
2112 if ((m_normalization != ColumnOp::NormalizeVisibleArea) || !overallMagChanged) { | 2182 if (!m_normalizeVisibleArea || !overallMagChanged) { |
2113 | 2183 |
2114 QRect areaLeft(0, 0, cache.getValidLeft(), h); | 2184 QRect areaLeft(0, 0, cache.getValidLeft(), h); |
2115 QRect areaRight(cache.getValidRight(), 0, | 2185 QRect areaRight(cache.getValidRight(), 0, |
2116 cache.getSize().width() - cache.getValidRight(), h); | 2186 cache.getSize().width() - cache.getValidRight(), h); |
2117 | 2187 |
3388 } | 3458 } |
3389 // SVDEBUG << "SpectrogramLayer::setMeasureRectYCoord: start " << r.startY << " <- " << y << ", end " << r.endY << " <- " << y << endl; | 3459 // SVDEBUG << "SpectrogramLayer::setMeasureRectYCoord: start " << r.startY << " <- " << y << ", end " << r.endY << " <- " << y << endl; |
3390 | 3460 |
3391 } | 3461 } |
3392 | 3462 |
3393 static ColourScale::Scale | |
3394 convertInColourScale(int fileScale) | |
3395 { | |
3396 switch (fileScale) { | |
3397 case 0: return ColourScale::LinearColourScale; | |
3398 case 1: return ColourScale::MeterColourScale; | |
3399 case 2: return ColourScale::LogColourScale; //!!! | |
3400 case 3: return ColourScale::LogColourScale; | |
3401 case 4: return ColourScale::PhaseColourScale; | |
3402 default: return ColourScale::LinearColourScale; | |
3403 } | |
3404 } | |
3405 | |
3406 static int | |
3407 convertOutColourScale(ColourScale::Scale scale) | |
3408 { | |
3409 switch (scale) { | |
3410 case ColourScale::LinearColourScale: return 0; | |
3411 case ColourScale::MeterColourScale: return 1; | |
3412 case ColourScale::LogColourScale: return 3; //!!! | |
3413 case ColourScale::PhaseColourScale: return 4; | |
3414 case ColourScale::PlusMinusOneScale: | |
3415 case ColourScale::AbsoluteScale: | |
3416 default: return 0; | |
3417 } | |
3418 } | |
3419 | |
3420 void | 3463 void |
3421 SpectrogramLayer::toXml(QTextStream &stream, | 3464 SpectrogramLayer::toXml(QTextStream &stream, |
3422 QString indent, QString extraAttributes) const | 3465 QString indent, QString extraAttributes) const |
3423 { | 3466 { |
3424 QString s; | 3467 QString s; |
3441 "colourRotation=\"%5\" " | 3484 "colourRotation=\"%5\" " |
3442 "frequencyScale=\"%6\" " | 3485 "frequencyScale=\"%6\" " |
3443 "binDisplay=\"%7\" ") | 3486 "binDisplay=\"%7\" ") |
3444 .arg(m_minFrequency) | 3487 .arg(m_minFrequency) |
3445 .arg(m_maxFrequency) | 3488 .arg(m_maxFrequency) |
3446 .arg(convertOutColourScale(m_colourScale)) | 3489 .arg(convertFromColourScale(m_colourScale)) |
3447 .arg(m_colourMap) | 3490 .arg(m_colourMap) |
3448 .arg(m_colourRotation) | 3491 .arg(m_colourRotation) |
3449 .arg(int(m_binScale)) | 3492 .arg(int(m_binScale)) |
3450 .arg(int(m_binDisplay)); | 3493 .arg(int(m_binDisplay)); |
3451 | 3494 |
3453 // normalization in future: write out the column normalization | 3496 // normalization in future: write out the column normalization |
3454 // type separately, and then whether we are normalizing visible | 3497 // type separately, and then whether we are normalizing visible |
3455 // area as well afterwards | 3498 // area as well afterwards |
3456 | 3499 |
3457 s += QString("columnNormalization=\"%1\" ") | 3500 s += QString("columnNormalization=\"%1\" ") |
3458 .arg(m_normalization == ColumnOp::NormalizeColumns ? "peak" : | 3501 .arg(m_normalization == ColumnNormalization::Max1 ? "peak" : |
3459 m_normalization == ColumnOp::NormalizeHybrid ? "hybrid" : "none"); | 3502 m_normalization == ColumnNormalization::Hybrid ? "hybrid" : "none"); |
3460 | 3503 |
3461 // Old-style normalization attribute. We *don't* write out | 3504 // Old-style normalization attribute. We *don't* write out |
3462 // normalizeHybrid here because the only release that would accept | 3505 // normalizeHybrid here because the only release that would accept |
3463 // it (Tony v1.0) has a totally different scale factor for | 3506 // it (Tony v1.0) has a totally different scale factor for |
3464 // it. We'll just have to accept that session files from Tony | 3507 // it. We'll just have to accept that session files from Tony |
3465 // v2.0+ will look odd in Tony v1.0 | 3508 // v2.0+ will look odd in Tony v1.0 |
3466 | 3509 |
3467 s += QString("normalizeColumns=\"%1\" ") | 3510 s += QString("normalizeColumns=\"%1\" ") |
3468 .arg(m_normalization == ColumnOp::NormalizeColumns ? "true" : "false"); | 3511 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); |
3469 | 3512 |
3470 // And this applies to both old- and new-style attributes | 3513 // And this applies to both old- and new-style attributes |
3471 | 3514 |
3472 s += QString("normalizeVisibleArea=\"%1\" ") | 3515 s += QString("normalizeVisibleArea=\"%1\" ") |
3473 .arg(m_normalization == ColumnOp::NormalizeVisibleArea ? "true" : "false"); | 3516 .arg(m_normalizeVisibleArea ? "true" : "false"); |
3474 | 3517 |
3475 Layer::toXml(stream, indent, extraAttributes + " " + s); | 3518 Layer::toXml(stream, indent, extraAttributes + " " + s); |
3476 } | 3519 } |
3477 | 3520 |
3478 void | 3521 void |
3516 if (ok) { | 3559 if (ok) { |
3517 SVDEBUG << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << endl; | 3560 SVDEBUG << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << endl; |
3518 setMaxFrequency(maxFrequency); | 3561 setMaxFrequency(maxFrequency); |
3519 } | 3562 } |
3520 | 3563 |
3521 ColourScale::Scale colourScale = convertInColourScale | 3564 ColourScale::Scale colourScale = convertToColourScale |
3522 (attributes.value("colourScale").toInt(&ok)); | 3565 (attributes.value("colourScale").toInt(&ok)); |
3523 if (ok) setColourScale(colourScale); | 3566 if (ok) setColourScale(colourScale); |
3524 | 3567 |
3525 int colourMap = attributes.value("colourScheme").toInt(&ok); | 3568 int colourMap = attributes.value("colourScheme").toInt(&ok); |
3526 if (ok) setColourMap(colourMap); | 3569 if (ok) setColourMap(colourMap); |
3543 if (columnNormalization != "") { | 3586 if (columnNormalization != "") { |
3544 | 3587 |
3545 haveNewStyleNormalization = true; | 3588 haveNewStyleNormalization = true; |
3546 | 3589 |
3547 if (columnNormalization == "peak") { | 3590 if (columnNormalization == "peak") { |
3548 setNormalization(ColumnOp::NormalizeColumns); | 3591 setNormalization(ColumnNormalization::Max1); |
3549 } else if (columnNormalization == "hybrid") { | 3592 } else if (columnNormalization == "hybrid") { |
3550 setNormalization(ColumnOp::NormalizeHybrid); | 3593 setNormalization(ColumnNormalization::Hybrid); |
3551 } else if (columnNormalization == "none") { | 3594 } else if (columnNormalization == "none") { |
3552 // do nothing | 3595 setNormalization(ColumnNormalization::None); |
3553 } else { | 3596 } else { |
3554 cerr << "NOTE: Unknown or unsupported columnNormalization attribute \"" | 3597 cerr << "NOTE: Unknown or unsupported columnNormalization attribute \"" |
3555 << columnNormalization << "\"" << endl; | 3598 << columnNormalization << "\"" << endl; |
3556 } | 3599 } |
3557 } | 3600 } |
3559 if (!haveNewStyleNormalization) { | 3602 if (!haveNewStyleNormalization) { |
3560 | 3603 |
3561 bool normalizeColumns = | 3604 bool normalizeColumns = |
3562 (attributes.value("normalizeColumns").trimmed() == "true"); | 3605 (attributes.value("normalizeColumns").trimmed() == "true"); |
3563 if (normalizeColumns) { | 3606 if (normalizeColumns) { |
3564 setNormalization(ColumnOp::NormalizeColumns); | 3607 setNormalization(ColumnNormalization::Max1); |
3565 } | 3608 } |
3566 | 3609 |
3567 bool normalizeHybrid = | 3610 bool normalizeHybrid = |
3568 (attributes.value("normalizeHybrid").trimmed() == "true"); | 3611 (attributes.value("normalizeHybrid").trimmed() == "true"); |
3569 if (normalizeHybrid) { | 3612 if (normalizeHybrid) { |
3570 setNormalization(ColumnOp::NormalizeHybrid); | 3613 setNormalization(ColumnNormalization::Hybrid); |
3571 } | 3614 } |
3572 } | 3615 } |
3573 | 3616 |
3574 bool normalizeVisibleArea = | 3617 bool normalizeVisibleArea = |
3575 (attributes.value("normalizeVisibleArea").trimmed() == "true"); | 3618 (attributes.value("normalizeVisibleArea").trimmed() == "true"); |
3576 if (normalizeVisibleArea) { | 3619 setNormalizeVisibleArea(normalizeVisibleArea); |
3577 setNormalization(ColumnOp::NormalizeVisibleArea); | 3620 |
3578 } | 3621 if (!haveNewStyleNormalization && m_normalization == ColumnNormalization::Hybrid) { |
3579 | |
3580 if (!haveNewStyleNormalization && m_normalization == ColumnOp::NormalizeHybrid) { | |
3581 // Tony v1.0 is (and hopefully will remain!) the only released | 3622 // Tony v1.0 is (and hopefully will remain!) the only released |
3582 // SV-a-like to use old-style attributes when saving sessions | 3623 // SV-a-like to use old-style attributes when saving sessions |
3583 // that ask for hybrid normalization. It saves them with the | 3624 // that ask for hybrid normalization. It saves them with the |
3584 // wrong gain factor, so hack in a fix for that here -- this | 3625 // wrong gain factor, so hack in a fix for that here -- this |
3585 // gives us backward but not forward compatibility. | 3626 // gives us backward but not forward compatibility. |