Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 997:296ccd36f626 tony-2.0-integration
Merge through to branch for Tony 2.0
author | Chris Cannam |
---|---|
date | Thu, 20 Aug 2015 14:54:21 +0100 |
parents | 4f4f0e158ecf |
children | 1a6304c547bf |
comparison
equal
deleted
inserted
replaced
943:788b7623bfca | 997:296ccd36f626 |
---|---|
71 m_initialMaxFrequency(8000), | 71 m_initialMaxFrequency(8000), |
72 m_colourScale(dBColourScale), | 72 m_colourScale(dBColourScale), |
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_normalization(NoNormalization), |
77 m_normalizeVisibleArea(false), | |
78 m_normalizeHybrid(false), | |
79 m_lastEmittedZoomStep(-1), | 77 m_lastEmittedZoomStep(-1), |
80 m_synchronous(false), | 78 m_synchronous(false), |
81 m_haveDetailedScale(false), | 79 m_haveDetailedScale(false), |
82 m_lastPaintBlockWidth(0), | 80 m_lastPaintBlockWidth(0), |
83 m_updateTimer(0), | |
84 m_candidateFillStartFrame(0), | |
85 m_exiting(false), | 81 m_exiting(false), |
86 m_sliceableModel(0) | 82 m_sliceableModel(0) |
87 { | 83 { |
88 if (config == FullRangeDb) { | 84 if (config == FullRangeDb) { |
89 m_initialMaxFrequency = 0; | 85 m_initialMaxFrequency = 0; |
105 setMaxFrequency(2000); | 101 setMaxFrequency(2000); |
106 setMinFrequency(40); | 102 setMinFrequency(40); |
107 setFrequencyScale(LogFrequencyScale); | 103 setFrequencyScale(LogFrequencyScale); |
108 setColourScale(LinearColourScale); | 104 setColourScale(LinearColourScale); |
109 setBinDisplay(PeakFrequencies); | 105 setBinDisplay(PeakFrequencies); |
110 setNormalizeColumns(true); | 106 setNormalization(NormalizeColumns); |
111 } | 107 } |
112 | 108 |
113 Preferences *prefs = Preferences::getInstance(); | 109 Preferences *prefs = Preferences::getInstance(); |
114 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), | 110 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), |
115 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); | 111 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); |
118 initialisePalette(); | 114 initialisePalette(); |
119 } | 115 } |
120 | 116 |
121 SpectrogramLayer::~SpectrogramLayer() | 117 SpectrogramLayer::~SpectrogramLayer() |
122 { | 118 { |
123 delete m_updateTimer; | |
124 m_updateTimer = 0; | |
125 | |
126 invalidateFFTModels(); | 119 invalidateFFTModels(); |
127 } | 120 } |
128 | 121 |
129 void | 122 void |
130 SpectrogramLayer::setModel(const DenseTimeValueModel *model) | 123 SpectrogramLayer::setModel(const DenseTimeValueModel *model) |
153 PropertyList list; | 146 PropertyList list; |
154 list.push_back("Colour"); | 147 list.push_back("Colour"); |
155 list.push_back("Colour Scale"); | 148 list.push_back("Colour Scale"); |
156 list.push_back("Window Size"); | 149 list.push_back("Window Size"); |
157 list.push_back("Window Increment"); | 150 list.push_back("Window Increment"); |
158 list.push_back("Normalize Columns"); | 151 list.push_back("Normalization"); |
159 list.push_back("Normalize Visible Area"); | |
160 list.push_back("Bin Display"); | 152 list.push_back("Bin Display"); |
161 list.push_back("Threshold"); | 153 list.push_back("Threshold"); |
162 list.push_back("Gain"); | 154 list.push_back("Gain"); |
163 list.push_back("Colour Rotation"); | 155 list.push_back("Colour Rotation"); |
164 // list.push_back("Min Frequency"); | 156 // list.push_back("Min Frequency"); |
173 { | 165 { |
174 if (name == "Colour") return tr("Colour"); | 166 if (name == "Colour") return tr("Colour"); |
175 if (name == "Colour Scale") return tr("Colour Scale"); | 167 if (name == "Colour Scale") return tr("Colour Scale"); |
176 if (name == "Window Size") return tr("Window Size"); | 168 if (name == "Window Size") return tr("Window Size"); |
177 if (name == "Window Increment") return tr("Window Overlap"); | 169 if (name == "Window Increment") return tr("Window Overlap"); |
178 if (name == "Normalize Columns") return tr("Normalize Columns"); | 170 if (name == "Normalization") return tr("Normalization"); |
179 if (name == "Normalize Visible Area") return tr("Normalize Visible Area"); | |
180 if (name == "Bin Display") return tr("Bin Display"); | 171 if (name == "Bin Display") return tr("Bin Display"); |
181 if (name == "Threshold") return tr("Threshold"); | 172 if (name == "Threshold") return tr("Threshold"); |
182 if (name == "Gain") return tr("Gain"); | 173 if (name == "Gain") return tr("Gain"); |
183 if (name == "Colour Rotation") return tr("Colour Rotation"); | 174 if (name == "Colour Rotation") return tr("Colour Rotation"); |
184 if (name == "Min Frequency") return tr("Min Frequency"); | 175 if (name == "Min Frequency") return tr("Min Frequency"); |
187 if (name == "Zero Padding") return tr("Smoothing"); | 178 if (name == "Zero Padding") return tr("Smoothing"); |
188 return ""; | 179 return ""; |
189 } | 180 } |
190 | 181 |
191 QString | 182 QString |
192 SpectrogramLayer::getPropertyIconName(const PropertyName &name) const | 183 SpectrogramLayer::getPropertyIconName(const PropertyName &) const |
193 { | 184 { |
194 if (name == "Normalize Columns") return "normalise-columns"; | |
195 if (name == "Normalize Visible Area") return "normalise"; | |
196 return ""; | 185 return ""; |
197 } | 186 } |
198 | 187 |
199 Layer::PropertyType | 188 Layer::PropertyType |
200 SpectrogramLayer::getPropertyType(const PropertyName &name) const | 189 SpectrogramLayer::getPropertyType(const PropertyName &name) const |
201 { | 190 { |
202 if (name == "Gain") return RangeProperty; | 191 if (name == "Gain") return RangeProperty; |
203 if (name == "Colour Rotation") return RangeProperty; | 192 if (name == "Colour Rotation") return RangeProperty; |
204 if (name == "Normalize Columns") return ToggleProperty; | |
205 if (name == "Normalize Visible Area") return ToggleProperty; | |
206 if (name == "Threshold") return RangeProperty; | 193 if (name == "Threshold") return RangeProperty; |
207 if (name == "Zero Padding") return ToggleProperty; | 194 if (name == "Zero Padding") return ToggleProperty; |
208 return ValueProperty; | 195 return ValueProperty; |
209 } | 196 } |
210 | 197 |
217 name == "Window Increment" || | 204 name == "Window Increment" || |
218 name == "Zero Padding") return tr("Window"); | 205 name == "Zero Padding") return tr("Window"); |
219 if (name == "Colour" || | 206 if (name == "Colour" || |
220 name == "Threshold" || | 207 name == "Threshold" || |
221 name == "Colour Rotation") return tr("Colour"); | 208 name == "Colour Rotation") return tr("Colour"); |
222 if (name == "Normalize Columns" || | 209 if (name == "Normalization" || |
223 name == "Normalize Visible Area" || | |
224 name == "Gain" || | 210 name == "Gain" || |
225 name == "Colour Scale") return tr("Scale"); | 211 name == "Colour Scale") return tr("Scale"); |
226 return QString(); | 212 return QString(); |
227 } | 213 } |
228 | 214 |
363 *min = 0; | 349 *min = 0; |
364 *max = 2; | 350 *max = 2; |
365 *deflt = int(AllBins); | 351 *deflt = int(AllBins); |
366 val = (int)m_binDisplay; | 352 val = (int)m_binDisplay; |
367 | 353 |
368 } else if (name == "Normalize Columns") { | 354 } else if (name == "Normalization") { |
369 | 355 |
370 *deflt = 0; | 356 *min = 0; |
371 val = (m_normalizeColumns ? 1 : 0); | 357 *max = 3; |
372 | 358 *deflt = int(NoNormalization); |
373 } else if (name == "Normalize Visible Area") { | 359 val = (int)m_normalization; |
374 | |
375 *deflt = 0; | |
376 val = (m_normalizeVisibleArea ? 1 : 0); | |
377 | 360 |
378 } else { | 361 } else { |
379 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | 362 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); |
380 } | 363 } |
381 | 364 |
396 case 1: return tr("Meter"); | 379 case 1: return tr("Meter"); |
397 case 2: return tr("dBV^2"); | 380 case 2: return tr("dBV^2"); |
398 case 3: return tr("dBV"); | 381 case 3: return tr("dBV"); |
399 case 4: return tr("Phase"); | 382 case 4: return tr("Phase"); |
400 } | 383 } |
384 } | |
385 if (name == "Normalization") { | |
386 return ""; // icon only | |
401 } | 387 } |
402 if (name == "Window Size") { | 388 if (name == "Window Size") { |
403 return QString("%1").arg(32 << value); | 389 return QString("%1").arg(32 << value); |
404 } | 390 } |
405 if (name == "Window Increment") { | 391 if (name == "Window Increment") { |
461 case 1: return tr("Peak Bins"); | 447 case 1: return tr("Peak Bins"); |
462 case 2: return tr("Frequencies"); | 448 case 2: return tr("Frequencies"); |
463 } | 449 } |
464 } | 450 } |
465 return tr("<unknown>"); | 451 return tr("<unknown>"); |
452 } | |
453 | |
454 QString | |
455 SpectrogramLayer::getPropertyValueIconName(const PropertyName &name, | |
456 int value) const | |
457 { | |
458 if (name == "Normalization") { | |
459 switch(value) { | |
460 default: | |
461 case 0: return "normalise-none"; | |
462 case 1: return "normalise-columns"; | |
463 case 2: return "normalise"; | |
464 case 3: return "normalise-hybrid"; | |
465 } | |
466 } | |
467 return ""; | |
466 } | 468 } |
467 | 469 |
468 RangeMapper * | 470 RangeMapper * |
469 SpectrogramLayer::getNewPropertyRangeMapper(const PropertyName &name) const | 471 SpectrogramLayer::getNewPropertyRangeMapper(const PropertyName &name) const |
470 { | 472 { |
553 default: | 555 default: |
554 case 0: setBinDisplay(AllBins); break; | 556 case 0: setBinDisplay(AllBins); break; |
555 case 1: setBinDisplay(PeakBins); break; | 557 case 1: setBinDisplay(PeakBins); break; |
556 case 2: setBinDisplay(PeakFrequencies); break; | 558 case 2: setBinDisplay(PeakFrequencies); break; |
557 } | 559 } |
558 } else if (name == "Normalize Columns") { | 560 } else if (name == "Normalization") { |
559 setNormalizeColumns(value ? true : false); | 561 switch (value) { |
560 } else if (name == "Normalize Visible Area") { | 562 default: |
561 setNormalizeVisibleArea(value ? true : false); | 563 case 0: setNormalization(NoNormalization); break; |
564 case 1: setNormalization(NormalizeColumns); break; | |
565 case 2: setNormalization(NormalizeVisibleArea); break; | |
566 case 3: setNormalization(NormalizeHybrid); break; | |
567 } | |
562 } | 568 } |
563 } | 569 } |
564 | 570 |
565 void | 571 void |
566 SpectrogramLayer::invalidateImageCaches() | 572 SpectrogramLayer::invalidateImageCaches() |
576 { | 582 { |
577 for (ViewImageCache::iterator i = m_imageCaches.begin(); | 583 for (ViewImageCache::iterator i = m_imageCaches.begin(); |
578 i != m_imageCaches.end(); ++i) { | 584 i != m_imageCaches.end(); ++i) { |
579 | 585 |
580 //!!! when are views removed from the map? on setLayerDormant? | 586 //!!! when are views removed from the map? on setLayerDormant? |
581 const View *v = i->first; | 587 const LayerGeometryProvider *v = i->first; |
582 | 588 |
583 #ifdef DEBUG_SPECTROGRAM_REPAINT | 589 #ifdef DEBUG_SPECTROGRAM_REPAINT |
584 SVDEBUG << "SpectrogramLayer::invalidateImageCaches(" | 590 cerr << "SpectrogramLayer::invalidateImageCaches(" |
585 << startFrame << ", " << endFrame << "): view range is " | 591 << startFrame << ", " << endFrame << "): view range is " |
586 << v->getStartFrame() << ", " << v->getEndFrame() | 592 << v->getStartFrame() << ", " << v->getEndFrame() |
587 << endl; | 593 << endl; |
588 | 594 |
589 cerr << "Valid area was: " << i->second.validArea.x() << ", " | 595 cerr << "Valid area was: " << i->second.validArea.x() << ", " |
599 #endif | 605 #endif |
600 return; | 606 return; |
601 } | 607 } |
602 int x = v->getXForFrame(startFrame); | 608 int x = v->getXForFrame(startFrame); |
603 #ifdef DEBUG_SPECTROGRAM_REPAINT | 609 #ifdef DEBUG_SPECTROGRAM_REPAINT |
604 SVDEBUG << "clipping from 0 to " << x-1 << endl; | 610 cerr << "clipping from 0 to " << x-1 << endl; |
605 #endif | 611 #endif |
606 if (x > 1) { | 612 if (x > 1) { |
607 i->second.validArea &= | 613 i->second.validArea &= |
608 QRect(0, 0, x-1, v->height()); | 614 QRect(0, 0, x-1, v->getPaintHeight()); |
609 } else { | 615 } else { |
610 i->second.validArea = QRect(); | 616 i->second.validArea = QRect(); |
611 } | 617 } |
612 } else { | 618 } else { |
613 if (int(endFrame) < v->getStartFrame()) { | 619 if (int(endFrame) < v->getStartFrame()) { |
616 #endif | 622 #endif |
617 return; | 623 return; |
618 } | 624 } |
619 int x = v->getXForFrame(endFrame); | 625 int x = v->getXForFrame(endFrame); |
620 #ifdef DEBUG_SPECTROGRAM_REPAINT | 626 #ifdef DEBUG_SPECTROGRAM_REPAINT |
621 SVDEBUG << "clipping from " << x+1 << " to " << v->width() | 627 cerr << "clipping from " << x+1 << " to " << v->getPaintWidth() |
622 << endl; | 628 << endl; |
623 #endif | 629 #endif |
624 if (x < v->width()) { | 630 if (x < v->getPaintWidth()) { |
625 i->second.validArea &= | 631 i->second.validArea &= |
626 QRect(x+1, 0, v->width()-(x+1), v->height()); | 632 QRect(x+1, 0, v->getPaintWidth()-(x+1), v->getPaintHeight()); |
627 } else { | 633 } else { |
628 i->second.validArea = QRect(); | 634 i->second.validArea = QRect(); |
629 } | 635 } |
630 } | 636 } |
631 | 637 |
932 { | 938 { |
933 return m_binDisplay; | 939 return m_binDisplay; |
934 } | 940 } |
935 | 941 |
936 void | 942 void |
937 SpectrogramLayer::setNormalizeColumns(bool n) | 943 SpectrogramLayer::setNormalization(Normalization n) |
938 { | 944 { |
939 if (m_normalizeColumns == n) return; | 945 if (m_normalization == n) return; |
940 | 946 |
941 invalidateImageCaches(); | 947 invalidateImageCaches(); |
942 invalidateMagnitudes(); | 948 invalidateMagnitudes(); |
943 m_normalizeColumns = n; | 949 m_normalization = n; |
944 | 950 |
945 emit layerParametersChanged(); | 951 emit layerParametersChanged(); |
946 } | 952 } |
947 | 953 |
948 bool | 954 SpectrogramLayer::Normalization |
949 SpectrogramLayer::getNormalizeColumns() const | 955 SpectrogramLayer::getNormalization() const |
950 { | 956 { |
951 return m_normalizeColumns; | 957 return m_normalization; |
952 } | 958 } |
953 | 959 |
954 void | 960 void |
955 SpectrogramLayer::setNormalizeHybrid(bool n) | 961 SpectrogramLayer::setLayerDormant(const LayerGeometryProvider *v, bool dormant) |
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 | |
973 SpectrogramLayer::setNormalizeVisibleArea(bool n) | |
974 { | |
975 SVDEBUG << "SpectrogramLayer::setNormalizeVisibleArea(" << n | |
976 << ") (from " << m_normalizeVisibleArea << ")" << endl; | |
977 | |
978 if (m_normalizeVisibleArea == n) return; | |
979 | |
980 invalidateImageCaches(); | |
981 invalidateMagnitudes(); | |
982 m_normalizeVisibleArea = n; | |
983 | |
984 emit layerParametersChanged(); | |
985 } | |
986 | |
987 bool | |
988 SpectrogramLayer::getNormalizeVisibleArea() const | |
989 { | |
990 return m_normalizeVisibleArea; | |
991 } | |
992 | |
993 void | |
994 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) | |
995 { | 962 { |
996 if (dormant) { | 963 if (dormant) { |
997 | 964 |
998 #ifdef DEBUG_SPECTROGRAM_REPAINT | 965 #ifdef DEBUG_SPECTROGRAM_REPAINT |
999 SVDEBUG << "SpectrogramLayer::setLayerDormant(" << dormant << ")" | 966 cerr << "SpectrogramLayer::setLayerDormant(" << dormant << ")" |
1000 << endl; | 967 << endl; |
1001 #endif | 968 #endif |
1002 | 969 |
1003 if (isLayerDormant(v)) { | 970 if (isLayerDormant(v)) { |
1004 return; | 971 return; |
1005 } | 972 } |
1006 | 973 |
1007 Layer::setLayerDormant(v, true); | 974 Layer::setLayerDormant(v, true); |
1008 | 975 |
976 const View *view = v->getView(); | |
977 | |
1009 invalidateImageCaches(); | 978 invalidateImageCaches(); |
1010 m_imageCaches.erase(v); | 979 |
1011 | 980 m_imageCaches.erase(view); |
1012 if (m_fftModels.find(v) != m_fftModels.end()) { | 981 |
1013 | 982 if (m_fftModels.find(view) != m_fftModels.end()) { |
1014 if (m_sliceableModel == m_fftModels[v].first) { | 983 |
984 if (m_sliceableModel == m_fftModels[view]) { | |
1015 bool replaced = false; | 985 bool replaced = false; |
1016 for (ViewFFTMap::iterator i = m_fftModels.begin(); | 986 for (ViewFFTMap::iterator i = m_fftModels.begin(); |
1017 i != m_fftModels.end(); ++i) { | 987 i != m_fftModels.end(); ++i) { |
1018 if (i->second.first != m_sliceableModel) { | 988 if (i->second != m_sliceableModel) { |
1019 emit sliceableModelReplaced(m_sliceableModel, i->second.first); | 989 emit sliceableModelReplaced(m_sliceableModel, i->second); |
1020 replaced = true; | 990 replaced = true; |
1021 break; | 991 break; |
1022 } | 992 } |
1023 } | 993 } |
1024 if (!replaced) emit sliceableModelReplaced(m_sliceableModel, 0); | 994 if (!replaced) emit sliceableModelReplaced(m_sliceableModel, 0); |
1025 } | 995 } |
1026 | 996 |
1027 delete m_fftModels[v].first; | 997 delete m_fftModels[view]; |
1028 m_fftModels.erase(v); | 998 m_fftModels.erase(view); |
1029 | 999 |
1030 delete m_peakCaches[v]; | 1000 delete m_peakCaches[view]; |
1031 m_peakCaches.erase(v); | 1001 m_peakCaches.erase(view); |
1032 } | 1002 } |
1033 | 1003 |
1034 } else { | 1004 } else { |
1035 | 1005 |
1036 Layer::setLayerDormant(v, false); | 1006 Layer::setLayerDormant(v, false); |
1039 | 1009 |
1040 void | 1010 void |
1041 SpectrogramLayer::cacheInvalid() | 1011 SpectrogramLayer::cacheInvalid() |
1042 { | 1012 { |
1043 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1013 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1044 SVDEBUG << "SpectrogramLayer::cacheInvalid()" << endl; | 1014 cerr << "SpectrogramLayer::cacheInvalid()" << endl; |
1045 #endif | 1015 #endif |
1046 | 1016 |
1047 invalidateImageCaches(); | 1017 invalidateImageCaches(); |
1048 invalidateMagnitudes(); | 1018 invalidateMagnitudes(); |
1049 } | 1019 } |
1050 | 1020 |
1051 void | 1021 void |
1052 SpectrogramLayer::cacheInvalid(sv_frame_t from, sv_frame_t to) | 1022 SpectrogramLayer::cacheInvalid(sv_frame_t from, sv_frame_t to) |
1053 { | 1023 { |
1054 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1024 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1055 SVDEBUG << "SpectrogramLayer::cacheInvalid(" << from << ", " << to << ")" << endl; | 1025 cerr << "SpectrogramLayer::cacheInvalid(" << from << ", " << to << ")" << endl; |
1056 #endif | 1026 #endif |
1057 | 1027 |
1058 invalidateImageCaches(from, to); | 1028 invalidateImageCaches(from, to); |
1059 invalidateMagnitudes(); | 1029 invalidateMagnitudes(); |
1060 } | |
1061 | |
1062 void | |
1063 SpectrogramLayer::fillTimerTimedOut() | |
1064 { | |
1065 if (!m_model) return; | |
1066 | |
1067 bool allDone = true; | |
1068 | |
1069 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1070 SVDEBUG << "SpectrogramLayer::fillTimerTimedOut: have " << m_fftModels.size() << " FFT models associated with views" << endl; | |
1071 #endif | |
1072 | |
1073 for (ViewFFTMap::iterator i = m_fftModels.begin(); | |
1074 i != m_fftModels.end(); ++i) { | |
1075 | |
1076 const FFTModel *model = i->second.first; | |
1077 sv_frame_t lastFill = i->second.second; | |
1078 | |
1079 if (model) { | |
1080 | |
1081 sv_frame_t fill = model->getFillExtent(); | |
1082 | |
1083 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1084 SVDEBUG << "SpectrogramLayer::fillTimerTimedOut: extent for " << model << ": " << fill << ", last " << lastFill << ", total " << m_model->getEndFrame() << endl; | |
1085 #endif | |
1086 | |
1087 if (fill >= lastFill) { | |
1088 if (fill >= m_model->getEndFrame() && lastFill > 0) { | |
1089 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1090 cerr << "complete!" << endl; | |
1091 #endif | |
1092 invalidateImageCaches(); | |
1093 i->second.second = -1; | |
1094 emit modelChanged(); | |
1095 | |
1096 } else if (fill > lastFill) { | |
1097 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1098 cerr << "SpectrogramLayer: emitting modelChanged(" | |
1099 << lastFill << "," << fill << ")" << endl; | |
1100 #endif | |
1101 invalidateImageCaches(lastFill, fill); | |
1102 i->second.second = fill; | |
1103 emit modelChangedWithin(lastFill, fill); | |
1104 } | |
1105 } else { | |
1106 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1107 cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" | |
1108 << m_model->getStartFrame() << "," << m_model->getEndFrame() << ")" << endl; | |
1109 #endif | |
1110 invalidateImageCaches(); | |
1111 i->second.second = fill; | |
1112 emit modelChangedWithin(m_model->getStartFrame(), m_model->getEndFrame()); | |
1113 } | |
1114 | |
1115 if (i->second.second >= 0) { | |
1116 allDone = false; | |
1117 } | |
1118 } | |
1119 } | |
1120 | |
1121 if (allDone) { | |
1122 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1123 cerr << "SpectrogramLayer: all complete!" << endl; | |
1124 #endif | |
1125 delete m_updateTimer; | |
1126 m_updateTimer = 0; | |
1127 } | |
1128 } | 1030 } |
1129 | 1031 |
1130 bool | 1032 bool |
1131 SpectrogramLayer::hasLightBackground() const | 1033 SpectrogramLayer::hasLightBackground() const |
1132 { | 1034 { |
1179 | 1081 |
1180 m_drawBuffer = QImage(); | 1082 m_drawBuffer = QImage(); |
1181 } | 1083 } |
1182 | 1084 |
1183 unsigned char | 1085 unsigned char |
1184 SpectrogramLayer::getDisplayValue(View *v, double input) const | 1086 SpectrogramLayer::getDisplayValue(LayerGeometryProvider *v, double input) const |
1185 { | 1087 { |
1186 int value; | 1088 int value; |
1187 | 1089 |
1188 double min = 0.0; | 1090 double min = 0.0; |
1189 double max = 1.0; | 1091 double max = 1.0; |
1190 | 1092 |
1191 if (m_normalizeVisibleArea) { | 1093 if (m_normalization == NormalizeVisibleArea) { |
1192 min = m_viewMags[v].getMin(); | 1094 min = m_viewMags[v].getMin(); |
1193 max = m_viewMags[v].getMax(); | 1095 max = m_viewMags[v].getMax(); |
1194 } else if (!m_normalizeColumns) { | 1096 } else if (m_normalization != NormalizeColumns) { |
1195 if (m_colourScale == LinearColourScale //|| | 1097 if (m_colourScale == LinearColourScale //|| |
1196 // m_colourScale == MeterColourScale) { | 1098 // m_colourScale == MeterColourScale) { |
1197 ) { | 1099 ) { |
1198 max = 0.1; | 1100 max = 0.1; |
1199 } | 1101 } |
1292 | 1194 |
1293 return maxf; | 1195 return maxf; |
1294 } | 1196 } |
1295 | 1197 |
1296 bool | 1198 bool |
1297 SpectrogramLayer::getYBinRange(View *v, int y, double &q0, double &q1) const | 1199 SpectrogramLayer::getYBinRange(LayerGeometryProvider *v, int y, double &q0, double &q1) const |
1298 { | 1200 { |
1299 Profiler profiler("SpectrogramLayer::getYBinRange"); | 1201 Profiler profiler("SpectrogramLayer::getYBinRange"); |
1300 | 1202 |
1301 int h = v->height(); | 1203 int h = v->getPaintHeight(); |
1302 if (y < 0 || y >= h) return false; | 1204 if (y < 0 || y >= h) return false; |
1303 | 1205 |
1304 sv_samplerate_t sr = m_model->getSampleRate(); | 1206 sv_samplerate_t sr = m_model->getSampleRate(); |
1305 double minf = getEffectiveMinFrequency(); | 1207 double minf = getEffectiveMinFrequency(); |
1306 double maxf = getEffectiveMaxFrequency(); | 1208 double maxf = getEffectiveMaxFrequency(); |
1318 | 1220 |
1319 return true; | 1221 return true; |
1320 } | 1222 } |
1321 | 1223 |
1322 bool | 1224 bool |
1323 SpectrogramLayer::getSmoothedYBinRange(View *v, int y, double &q0, double &q1) const | 1225 SpectrogramLayer::getSmoothedYBinRange(LayerGeometryProvider *v, int y, double &q0, double &q1) const |
1324 { | 1226 { |
1325 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange"); | 1227 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange"); |
1326 | 1228 |
1327 int h = v->height(); | 1229 int h = v->getPaintHeight(); |
1328 if (y < 0 || y >= h) return false; | 1230 if (y < 0 || y >= h) return false; |
1329 | 1231 |
1330 sv_samplerate_t sr = m_model->getSampleRate(); | 1232 sv_samplerate_t sr = m_model->getSampleRate(); |
1331 double minf = getEffectiveMinFrequency(); | 1233 double minf = getEffectiveMinFrequency(); |
1332 double maxf = getEffectiveMaxFrequency(); | 1234 double maxf = getEffectiveMaxFrequency(); |
1344 | 1246 |
1345 return true; | 1247 return true; |
1346 } | 1248 } |
1347 | 1249 |
1348 bool | 1250 bool |
1349 SpectrogramLayer::getXBinRange(View *v, int x, double &s0, double &s1) const | 1251 SpectrogramLayer::getXBinRange(LayerGeometryProvider *v, int x, double &s0, double &s1) const |
1350 { | 1252 { |
1351 sv_frame_t modelStart = m_model->getStartFrame(); | 1253 sv_frame_t modelStart = m_model->getStartFrame(); |
1352 sv_frame_t modelEnd = m_model->getEndFrame(); | 1254 sv_frame_t modelEnd = m_model->getEndFrame(); |
1353 | 1255 |
1354 // Each pixel column covers an exact range of sample frames: | 1256 // Each pixel column covers an exact range of sample frames: |
1368 | 1270 |
1369 return true; | 1271 return true; |
1370 } | 1272 } |
1371 | 1273 |
1372 bool | 1274 bool |
1373 SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const | 1275 SpectrogramLayer::getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &min, RealTime &max) const |
1374 { | 1276 { |
1375 double s0 = 0, s1 = 0; | 1277 double s0 = 0, s1 = 0; |
1376 if (!getXBinRange(v, x, s0, s1)) return false; | 1278 if (!getXBinRange(v, x, s0, s1)) return false; |
1377 | 1279 |
1378 int s0i = int(s0 + 0.001); | 1280 int s0i = int(s0 + 0.001); |
1387 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); | 1289 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); |
1388 return true; | 1290 return true; |
1389 } | 1291 } |
1390 | 1292 |
1391 bool | 1293 bool |
1392 SpectrogramLayer::getYBinSourceRange(View *v, int y, double &freqMin, double &freqMax) | 1294 SpectrogramLayer::getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) |
1393 const | 1295 const |
1394 { | 1296 { |
1395 double q0 = 0, q1 = 0; | 1297 double q0 = 0, q1 = 0; |
1396 if (!getYBinRange(v, y, q0, q1)) return false; | 1298 if (!getYBinRange(v, y, q0, q1)) return false; |
1397 | 1299 |
1406 } | 1308 } |
1407 return true; | 1309 return true; |
1408 } | 1310 } |
1409 | 1311 |
1410 bool | 1312 bool |
1411 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, | 1313 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, |
1412 double &freqMin, double &freqMax, | 1314 double &freqMin, double &freqMax, |
1413 double &adjFreqMin, double &adjFreqMax) | 1315 double &adjFreqMin, double &adjFreqMax) |
1414 const | 1316 const |
1415 { | 1317 { |
1416 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1318 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1473 | 1375 |
1474 return haveAdj; | 1376 return haveAdj; |
1475 } | 1377 } |
1476 | 1378 |
1477 bool | 1379 bool |
1478 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y, | 1380 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, |
1479 double &min, double &max, | 1381 double &min, double &max, |
1480 double &phaseMin, double &phaseMax) const | 1382 double &phaseMin, double &phaseMax) const |
1481 { | 1383 { |
1482 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1384 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1483 return false; | 1385 return false; |
1542 | 1444 |
1543 return rv; | 1445 return rv; |
1544 } | 1446 } |
1545 | 1447 |
1546 int | 1448 int |
1547 SpectrogramLayer::getZeroPadLevel(const View *v) const | 1449 SpectrogramLayer::getZeroPadLevel(const LayerGeometryProvider *v) const |
1548 { | 1450 { |
1549 //!!! tidy all this stuff | 1451 //!!! tidy all this stuff |
1550 | 1452 |
1551 if (m_binDisplay != AllBins) return 0; | 1453 if (m_binDisplay != AllBins) return 0; |
1552 | 1454 |
1572 if (minbin < 1) minbin = 1; | 1474 if (minbin < 1) minbin = 1; |
1573 if (minbin >= maxbin) minbin = maxbin - 1; | 1475 if (minbin >= maxbin) minbin = maxbin - 1; |
1574 } | 1476 } |
1575 | 1477 |
1576 double perPixel = | 1478 double perPixel = |
1577 double(v->height()) / | 1479 double(v->getPaintHeight()) / |
1578 double((maxbin - minbin) / (m_zeroPadLevel + 1)); | 1480 double((maxbin - minbin) / (m_zeroPadLevel + 1)); |
1579 | 1481 |
1580 if (perPixel > 2.8) { | 1482 if (perPixel > 2.8) { |
1581 return 3; // 4x oversampling | 1483 return 3; // 4x oversampling |
1582 } else if (perPixel > 1.5) { | 1484 } else if (perPixel > 1.5) { |
1585 return 0; // 1x | 1487 return 0; // 1x |
1586 } | 1488 } |
1587 } | 1489 } |
1588 | 1490 |
1589 int | 1491 int |
1590 SpectrogramLayer::getFFTSize(const View *v) const | 1492 SpectrogramLayer::getFFTSize(const LayerGeometryProvider *v) const |
1591 { | 1493 { |
1592 return m_fftSize * (getZeroPadLevel(v) + 1); | 1494 return m_fftSize * (getZeroPadLevel(v) + 1); |
1593 } | 1495 } |
1594 | 1496 |
1595 FFTModel * | 1497 FFTModel * |
1596 SpectrogramLayer::getFFTModel(const View *v) const | 1498 SpectrogramLayer::getFFTModel(const LayerGeometryProvider *v) const |
1597 { | 1499 { |
1598 if (!m_model) return 0; | 1500 if (!m_model) return 0; |
1599 | 1501 |
1600 int fftSize = getFFTSize(v); | 1502 int fftSize = getFFTSize(v); |
1601 | 1503 |
1602 if (m_fftModels.find(v) != m_fftModels.end()) { | 1504 const View *view = v->getView(); |
1603 if (m_fftModels[v].first == 0) { | 1505 |
1604 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1506 if (m_fftModels.find(view) != m_fftModels.end()) { |
1605 SVDEBUG << "SpectrogramLayer::getFFTModel(" << v << "): Found null model" << endl; | 1507 if (m_fftModels[view] == 0) { |
1508 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1509 cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found null model" << endl; | |
1606 #endif | 1510 #endif |
1607 return 0; | 1511 return 0; |
1608 } | 1512 } |
1609 if (m_fftModels[v].first->getHeight() != fftSize / 2 + 1) { | 1513 if (m_fftModels[view]->getHeight() != fftSize / 2 + 1) { |
1610 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1514 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1611 SVDEBUG << "SpectrogramLayer::getFFTModel(" << v << "): Found a model with the wrong height (" << m_fftModels[v].first->getHeight() << ", wanted " << (fftSize / 2 + 1) << ")" << endl; | 1515 cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a model with the wrong height (" << m_fftModels[view].first->getHeight() << ", wanted " << (fftSize / 2 + 1) << ")" << endl; |
1612 #endif | 1516 #endif |
1613 delete m_fftModels[v].first; | 1517 delete m_fftModels[view]; |
1614 m_fftModels.erase(v); | 1518 m_fftModels.erase(view); |
1615 delete m_peakCaches[v]; | 1519 delete m_peakCaches[view]; |
1616 m_peakCaches.erase(v); | 1520 m_peakCaches.erase(view); |
1617 } else { | 1521 } else { |
1618 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1522 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1619 SVDEBUG << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[v].first->getHeight() << endl; | 1523 cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[view]->getHeight() << endl; |
1620 #endif | 1524 #endif |
1621 return m_fftModels[v].first; | 1525 return m_fftModels[view]; |
1622 } | 1526 } |
1623 } | 1527 } |
1624 | 1528 |
1625 if (m_fftModels.find(v) == m_fftModels.end()) { | 1529 if (m_fftModels.find(view) == m_fftModels.end()) { |
1626 | 1530 |
1627 FFTModel *model = new FFTModel(m_model, | 1531 FFTModel *model = new FFTModel(m_model, |
1628 m_channel, | 1532 m_channel, |
1629 m_windowType, | 1533 m_windowType, |
1630 m_windowSize, | 1534 m_windowSize, |
1631 getWindowIncrement(), | 1535 getWindowIncrement(), |
1632 fftSize, | 1536 fftSize); |
1633 true, // polar | |
1634 StorageAdviser::SpeedCritical, | |
1635 m_candidateFillStartFrame); | |
1636 | 1537 |
1637 if (!model->isOK()) { | 1538 if (!model->isOK()) { |
1638 QMessageBox::critical | 1539 QMessageBox::critical |
1639 (0, tr("FFT cache failed"), | 1540 (0, tr("FFT cache failed"), |
1640 tr("Failed to create the FFT model for this spectrogram.\n" | 1541 tr("Failed to create the FFT model for this spectrogram.\n" |
1641 "There may be insufficient memory or disc space to continue.")); | 1542 "There may be insufficient memory or disc space to continue.")); |
1642 delete model; | 1543 delete model; |
1643 m_fftModels[v] = FFTFillPair(0, 0); | 1544 m_fftModels[view] = 0; |
1644 return 0; | 1545 return 0; |
1645 } | 1546 } |
1646 | 1547 |
1647 if (!m_sliceableModel) { | 1548 if (!m_sliceableModel) { |
1648 #ifdef DEBUG_SPECTROGRAM | 1549 #ifdef DEBUG_SPECTROGRAM |
1650 #endif | 1551 #endif |
1651 ((SpectrogramLayer *)this)->sliceableModelReplaced(0, model); | 1552 ((SpectrogramLayer *)this)->sliceableModelReplaced(0, model); |
1652 m_sliceableModel = model; | 1553 m_sliceableModel = model; |
1653 } | 1554 } |
1654 | 1555 |
1655 m_fftModels[v] = FFTFillPair(model, 0); | 1556 m_fftModels[view] = model; |
1656 | 1557 } |
1657 model->resume(); | 1558 |
1658 | 1559 return m_fftModels[view]; |
1659 delete m_updateTimer; | |
1660 m_updateTimer = new QTimer((SpectrogramLayer *)this); | |
1661 connect(m_updateTimer, SIGNAL(timeout()), | |
1662 this, SLOT(fillTimerTimedOut())); | |
1663 m_updateTimer->start(200); | |
1664 } | |
1665 | |
1666 return m_fftModels[v].first; | |
1667 } | 1560 } |
1668 | 1561 |
1669 Dense3DModelPeakCache * | 1562 Dense3DModelPeakCache * |
1670 SpectrogramLayer::getPeakCache(const View *v) const | 1563 SpectrogramLayer::getPeakCache(const LayerGeometryProvider *v) const |
1671 { | 1564 { |
1672 if (!m_peakCaches[v]) { | 1565 const View *view = v->getView(); |
1566 if (!m_peakCaches[view]) { | |
1673 FFTModel *f = getFFTModel(v); | 1567 FFTModel *f = getFFTModel(v); |
1674 if (!f) return 0; | 1568 if (!f) return 0; |
1675 m_peakCaches[v] = new Dense3DModelPeakCache(f, 8); | 1569 m_peakCaches[view] = new Dense3DModelPeakCache(f, 8); |
1676 } | 1570 } |
1677 return m_peakCaches[v]; | 1571 return m_peakCaches[view]; |
1678 } | 1572 } |
1679 | 1573 |
1680 const Model * | 1574 const Model * |
1681 SpectrogramLayer::getSliceableModel() const | 1575 SpectrogramLayer::getSliceableModel() const |
1682 { | 1576 { |
1683 if (m_sliceableModel) return m_sliceableModel; | 1577 if (m_sliceableModel) return m_sliceableModel; |
1684 if (m_fftModels.empty()) return 0; | 1578 if (m_fftModels.empty()) return 0; |
1685 m_sliceableModel = m_fftModels.begin()->second.first; | 1579 m_sliceableModel = m_fftModels.begin()->second; |
1686 return m_sliceableModel; | 1580 return m_sliceableModel; |
1687 } | 1581 } |
1688 | 1582 |
1689 void | 1583 void |
1690 SpectrogramLayer::invalidateFFTModels() | 1584 SpectrogramLayer::invalidateFFTModels() |
1691 { | 1585 { |
1692 for (ViewFFTMap::iterator i = m_fftModels.begin(); | 1586 for (ViewFFTMap::iterator i = m_fftModels.begin(); |
1693 i != m_fftModels.end(); ++i) { | 1587 i != m_fftModels.end(); ++i) { |
1694 delete i->second.first; | 1588 delete i->second; |
1695 } | 1589 } |
1696 for (PeakCacheMap::iterator i = m_peakCaches.begin(); | 1590 for (PeakCacheMap::iterator i = m_peakCaches.begin(); |
1697 i != m_peakCaches.end(); ++i) { | 1591 i != m_peakCaches.end(); ++i) { |
1698 delete i->second; | 1592 delete i->second; |
1699 } | 1593 } |
1717 *i = MagnitudeRange(); | 1611 *i = MagnitudeRange(); |
1718 } | 1612 } |
1719 } | 1613 } |
1720 | 1614 |
1721 bool | 1615 bool |
1722 SpectrogramLayer::updateViewMagnitudes(View *v) const | 1616 SpectrogramLayer::updateViewMagnitudes(LayerGeometryProvider *v) const |
1723 { | 1617 { |
1724 MagnitudeRange mag; | 1618 MagnitudeRange mag; |
1725 | 1619 |
1726 int x0 = 0, x1 = v->width(); | 1620 int x0 = 0, x1 = v->getPaintWidth(); |
1727 double s00 = 0, s01 = 0, s10 = 0, s11 = 0; | 1621 double s00 = 0, s01 = 0, s10 = 0, s11 = 0; |
1728 | 1622 |
1729 if (!getXBinRange(v, x0, s00, s01)) { | 1623 if (!getXBinRange(v, x0, s00, s01)) { |
1730 s00 = s01 = double(m_model->getStartFrame()) / getWindowIncrement(); | 1624 s00 = s01 = double(m_model->getStartFrame()) / getWindowIncrement(); |
1731 } | 1625 } |
1748 mag.sample(m_columnMags[s]); | 1642 mag.sample(m_columnMags[s]); |
1749 } | 1643 } |
1750 } | 1644 } |
1751 | 1645 |
1752 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1646 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1753 SVDEBUG << "SpectrogramLayer::updateViewMagnitudes returning from cols " | 1647 cerr << "SpectrogramLayer::updateViewMagnitudes returning from cols " |
1754 << s0 << " -> " << s1 << " inclusive" << endl; | 1648 << s0 << " -> " << s1 << " inclusive" << endl; |
1755 #endif | 1649 #endif |
1756 | 1650 |
1757 if (!mag.isSet()) return false; | 1651 if (!mag.isSet()) return false; |
1758 if (mag == m_viewMags[v]) return false; | 1652 if (mag == m_viewMags[v]) return false; |
1765 { | 1659 { |
1766 m_synchronous = synchronous; | 1660 m_synchronous = synchronous; |
1767 } | 1661 } |
1768 | 1662 |
1769 void | 1663 void |
1770 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const | 1664 SpectrogramLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
1771 { | 1665 { |
1772 // What a lovely, old-fashioned function this is. | 1666 // What a lovely, old-fashioned function this is. |
1773 // It's practically FORTRAN 77 in its clarity and linearity. | 1667 // It's practically FORTRAN 77 in its clarity and linearity. |
1774 | 1668 |
1775 Profiler profiler("SpectrogramLayer::paint", false); | 1669 Profiler profiler("SpectrogramLayer::paint", false); |
1776 | 1670 |
1777 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1671 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1778 SVDEBUG << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << endl; | 1672 cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << endl; |
1779 | 1673 |
1780 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; | 1674 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; |
1781 #endif | 1675 #endif |
1782 | 1676 |
1783 sv_frame_t startFrame = v->getStartFrame(); | 1677 sv_frame_t startFrame = v->getStartFrame(); |
1784 if (startFrame < 0) m_candidateFillStartFrame = 0; | |
1785 else m_candidateFillStartFrame = startFrame; | |
1786 | 1678 |
1787 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1679 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1788 return; | 1680 return; |
1789 } | 1681 } |
1790 | 1682 |
1805 if (!fft) { | 1697 if (!fft) { |
1806 cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << endl; | 1698 cerr << "ERROR: SpectrogramLayer::paint(): No FFT model, returning" << endl; |
1807 return; | 1699 return; |
1808 } | 1700 } |
1809 */ | 1701 */ |
1810 ImageCache &cache = m_imageCaches[v]; | 1702 |
1811 | 1703 const View *view = v->getView(); |
1812 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1704 |
1813 SVDEBUG << "SpectrogramLayer::paint(): image cache valid area " << cache. | 1705 ImageCache &cache = m_imageCaches[view]; |
1706 | |
1707 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1708 cerr << "SpectrogramLayer::paint(): image cache valid area " << cache. | |
1814 | 1709 |
1815 validArea.x() << ", " << cache.validArea.y() << ", " << cache.validArea.width() << "x" << cache.validArea.height() << endl; | 1710 validArea.x() << ", " << cache.validArea.y() << ", " << cache.validArea.width() << "x" << cache.validArea.height() << endl; |
1816 #endif | 1711 #endif |
1817 | 1712 |
1818 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1819 bool stillCacheing = (m_updateTimer != 0); | |
1820 SVDEBUG << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << endl; | |
1821 #endif | |
1822 | |
1823 int zoomLevel = v->getZoomLevel(); | 1713 int zoomLevel = v->getZoomLevel(); |
1824 | 1714 |
1825 int x0 = 0; | 1715 int x0 = 0; |
1826 int x1 = v->width(); | 1716 int x1 = v->getPaintWidth(); |
1827 | 1717 |
1828 bool recreateWholeImageCache = true; | 1718 bool recreateWholeImageCache = true; |
1829 | 1719 |
1830 x0 = rect.left(); | 1720 x0 = rect.left(); |
1831 x1 = rect.right() + 1; | 1721 x1 = rect.right() + 1; |
1838 | 1728 |
1839 int cw = cache.image.width(); | 1729 int cw = cache.image.width(); |
1840 int ch = cache.image.height(); | 1730 int ch = cache.image.height(); |
1841 | 1731 |
1842 if (int(cache.zoomLevel) == zoomLevel && | 1732 if (int(cache.zoomLevel) == zoomLevel && |
1843 cw == v->width() && | 1733 cw == v->getPaintWidth() && |
1844 ch == v->height()) { | 1734 ch == v->getPaintHeight()) { |
1845 | 1735 |
1846 if (v->getXForFrame(cache.startFrame) == | 1736 if (v->getXForFrame(cache.startFrame) == |
1847 v->getXForFrame(startFrame) && | 1737 v->getXForFrame(startFrame) && |
1848 cache.validArea.x() <= x0 && | 1738 cache.validArea.x() <= x0 && |
1849 cache.validArea.x() + cache.validArea.width() >= x1) { | 1739 cache.validArea.x() + cache.validArea.width() >= x1) { |
1945 cerr << "SpectrogramLayer: image cache useless" << endl; | 1835 cerr << "SpectrogramLayer: image cache useless" << endl; |
1946 if (int(cache.zoomLevel) != zoomLevel) { | 1836 if (int(cache.zoomLevel) != zoomLevel) { |
1947 cerr << "(cache zoomLevel " << cache.zoomLevel | 1837 cerr << "(cache zoomLevel " << cache.zoomLevel |
1948 << " != " << zoomLevel << ")" << endl; | 1838 << " != " << zoomLevel << ")" << endl; |
1949 } | 1839 } |
1950 if (cw != v->width()) { | 1840 if (cw != v->getPaintWidth()) { |
1951 cerr << "(cache width " << cw | 1841 cerr << "(cache width " << cw |
1952 << " != " << v->width(); | 1842 << " != " << v->getPaintWidth(); |
1953 } | 1843 } |
1954 if (ch != v->height()) { | 1844 if (ch != v->getPaintHeight()) { |
1955 cerr << "(cache height " << ch | 1845 cerr << "(cache height " << ch |
1956 << " != " << v->height(); | 1846 << " != " << v->getPaintHeight(); |
1957 } | 1847 } |
1958 #endif | 1848 #endif |
1959 cache.validArea = QRect(); | 1849 cache.validArea = QRect(); |
1960 // recreateWholeImageCache = true; | 1850 // recreateWholeImageCache = true; |
1961 } | 1851 } |
1963 | 1853 |
1964 if (updateViewMagnitudes(v)) { | 1854 if (updateViewMagnitudes(v)) { |
1965 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1855 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1966 cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << endl; | 1856 cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << endl; |
1967 #endif | 1857 #endif |
1968 if (m_normalizeVisibleArea) { | 1858 if (m_normalization == NormalizeVisibleArea) { |
1969 cache.validArea = QRect(); | 1859 cache.validArea = QRect(); |
1970 recreateWholeImageCache = true; | 1860 recreateWholeImageCache = true; |
1971 } | 1861 } |
1972 } else { | 1862 } else { |
1973 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1863 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1975 #endif | 1865 #endif |
1976 } | 1866 } |
1977 | 1867 |
1978 if (recreateWholeImageCache) { | 1868 if (recreateWholeImageCache) { |
1979 x0 = 0; | 1869 x0 = 0; |
1980 x1 = v->width(); | 1870 x1 = v->getPaintWidth(); |
1981 } | 1871 } |
1982 | 1872 |
1983 struct timeval tv; | 1873 struct timeval tv; |
1984 (void)gettimeofday(&tv, 0); | 1874 (void)gettimeofday(&tv, 0); |
1985 RealTime mainPaintStart = RealTime::fromTimeval(tv); | 1875 RealTime mainPaintStart = RealTime::fromTimeval(tv); |
2019 // Smaller heights can be used when painting direct from cache | 1909 // Smaller heights can be used when painting direct from cache |
2020 // (further up in this function), but we want to ensure the cache | 1910 // (further up in this function), but we want to ensure the cache |
2021 // is coherent without having to worry about vertical matching of | 1911 // is coherent without having to worry about vertical matching of |
2022 // required and valid areas as well as horizontal. | 1912 // required and valid areas as well as horizontal. |
2023 | 1913 |
2024 int h = v->height(); | 1914 int h = v->getPaintHeight(); |
2025 | 1915 |
2026 if (cache.validArea.width() > 0) { | 1916 if (cache.validArea.width() > 0) { |
2027 | 1917 |
2028 // If part of the cache is known to be valid, select a strip | 1918 // If part of the cache is known to be valid, select a strip |
2029 // immediately to left or right of the valid part | 1919 // immediately to left or right of the valid part |
2172 | 2062 |
2173 if (w == 0) { | 2063 if (w == 0) { |
2174 SVDEBUG << "*** NOTE: w == 0" << endl; | 2064 SVDEBUG << "*** NOTE: w == 0" << endl; |
2175 } | 2065 } |
2176 | 2066 |
2177 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
2178 int pixels = 0; | |
2179 #endif | |
2180 | |
2181 Profiler outerprof("SpectrogramLayer::paint: all cols"); | 2067 Profiler outerprof("SpectrogramLayer::paint: all cols"); |
2182 | 2068 |
2183 // The draw buffer contains a fragment at either our pixel | 2069 // The draw buffer contains a fragment at either our pixel |
2184 // resolution (if there is more than one time-bin per pixel) or | 2070 // resolution (if there is more than one time-bin per pixel) or |
2185 // time-bin resolution (if a time-bin spans more than one pixel). | 2071 // time-bin resolution (if a time-bin spans more than one pixel). |
2326 | 2212 |
2327 Profiler profiler2("SpectrogramLayer::paint: draw image"); | 2213 Profiler profiler2("SpectrogramLayer::paint: draw image"); |
2328 | 2214 |
2329 if (recreateWholeImageCache) { | 2215 if (recreateWholeImageCache) { |
2330 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2216 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2331 SVDEBUG << "Recreating image cache: width = " << v->width() | 2217 cerr << "Recreating image cache: width = " << v->getPaintWidth() |
2332 << ", height = " << h << endl; | 2218 << ", height = " << h << endl; |
2333 #endif | 2219 #endif |
2334 cache.image = QImage(v->width(), h, QImage::Format_ARGB32_Premultiplied); | 2220 cache.image = QImage(v->getPaintWidth(), h, QImage::Format_ARGB32_Premultiplied); |
2335 } | 2221 } |
2336 | 2222 |
2337 if (w > 0) { | 2223 if (w > 0) { |
2338 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2224 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2339 SVDEBUG << "Painting " << w << "x" << h | 2225 cerr << "Painting " << w << "x" << h |
2340 << " from draw buffer at " << 0 << "," << 0 | 2226 << " from draw buffer at " << 0 << "," << 0 |
2341 << " to " << w << "x" << h << " on cache at " | 2227 << " to " << w << "x" << h << " on cache at " |
2342 << x0 << "," << 0 << endl; | 2228 << x0 << "," << 0 << endl; |
2343 #endif | 2229 #endif |
2344 | 2230 |
2346 | 2232 |
2347 if (bufferBinResolution) { | 2233 if (bufferBinResolution) { |
2348 int scaledLeft = v->getXForFrame(leftBoundaryFrame); | 2234 int scaledLeft = v->getXForFrame(leftBoundaryFrame); |
2349 int scaledRight = v->getXForFrame(rightBoundaryFrame); | 2235 int scaledRight = v->getXForFrame(rightBoundaryFrame); |
2350 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2236 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2351 SVDEBUG << "Rescaling image from " << bufwid | 2237 cerr << "Rescaling image from " << bufwid |
2352 << "x" << h << " to " | 2238 << "x" << h << " to " |
2353 << scaledRight-scaledLeft << "x" << h << endl; | 2239 << scaledRight-scaledLeft << "x" << h << endl; |
2354 #endif | 2240 #endif |
2355 Preferences::SpectrogramXSmoothing xsmoothing = | 2241 Preferences::SpectrogramXSmoothing xsmoothing = |
2356 Preferences::getInstance()->getSpectrogramXSmoothing(); | 2242 Preferences::getInstance()->getSpectrogramXSmoothing(); |
2361 ((xsmoothing == Preferences::SpectrogramXInterpolated) ? | 2247 ((xsmoothing == Preferences::SpectrogramXInterpolated) ? |
2362 Qt::SmoothTransformation : Qt::FastTransformation)); | 2248 Qt::SmoothTransformation : Qt::FastTransformation)); |
2363 int scaledLeftCrop = v->getXForFrame(leftCropFrame); | 2249 int scaledLeftCrop = v->getXForFrame(leftCropFrame); |
2364 int scaledRightCrop = v->getXForFrame(rightCropFrame); | 2250 int scaledRightCrop = v->getXForFrame(rightCropFrame); |
2365 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2251 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2366 SVDEBUG << "Drawing image region of width " << scaledRightCrop - scaledLeftCrop << " to " | 2252 cerr << "Drawing image region of width " << scaledRightCrop - scaledLeftCrop << " to " |
2367 << scaledLeftCrop << " from " << scaledLeftCrop - scaledLeft << endl; | 2253 << scaledLeftCrop << " from " << scaledLeftCrop - scaledLeft << endl; |
2368 #endif | 2254 #endif |
2369 cachePainter.drawImage | 2255 cachePainter.drawImage |
2370 (QRect(scaledLeftCrop, 0, | 2256 (QRect(scaledLeftCrop, 0, |
2371 scaledRightCrop - scaledLeftCrop, h), | 2257 scaledRightCrop - scaledLeftCrop, h), |
2382 } | 2268 } |
2383 | 2269 |
2384 QRect pr = rect & cache.validArea; | 2270 QRect pr = rect & cache.validArea; |
2385 | 2271 |
2386 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2272 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2387 SVDEBUG << "Painting " << pr.width() << "x" << pr.height() | 2273 cerr << "Painting " << pr.width() << "x" << pr.height() |
2388 << " from cache at " << pr.x() << "," << pr.y() | 2274 << " from cache at " << pr.x() << "," << pr.y() |
2389 << " to window" << endl; | 2275 << " to window" << endl; |
2390 #endif | 2276 #endif |
2391 | 2277 |
2392 paint.drawImage(pr.x(), pr.y(), cache.image, | 2278 paint.drawImage(pr.x(), pr.y(), cache.image, |
2398 cache.startFrame = startFrame; | 2284 cache.startFrame = startFrame; |
2399 cache.zoomLevel = zoomLevel; | 2285 cache.zoomLevel = zoomLevel; |
2400 | 2286 |
2401 if (!m_synchronous) { | 2287 if (!m_synchronous) { |
2402 | 2288 |
2403 if (!m_normalizeVisibleArea || !overallMagChanged) { | 2289 if ((m_normalization != NormalizeVisibleArea) || !overallMagChanged) { |
2404 | 2290 |
2405 if (cache.validArea.x() > 0) { | 2291 if (cache.validArea.x() > 0) { |
2406 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2292 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2407 SVDEBUG << "SpectrogramLayer::paint() updating left (0, " | 2293 cerr << "SpectrogramLayer::paint() updating left (0, " |
2408 << cache.validArea.x() << ")" << endl; | 2294 << cache.validArea.x() << ")" << endl; |
2409 #endif | 2295 #endif |
2410 v->update(0, 0, cache.validArea.x(), h); | 2296 v->getView()->update(0, 0, cache.validArea.x(), h); |
2411 } | 2297 } |
2412 | 2298 |
2413 if (cache.validArea.x() + cache.validArea.width() < | 2299 if (cache.validArea.x() + cache.validArea.width() < |
2414 cache.image.width()) { | 2300 cache.image.width()) { |
2415 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2301 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2416 SVDEBUG << "SpectrogramLayer::paint() updating right (" | 2302 cerr << "SpectrogramLayer::paint() updating right (" |
2417 << cache.validArea.x() + cache.validArea.width() | 2303 << cache.validArea.x() + cache.validArea.width() |
2418 << ", " | 2304 << ", " |
2419 << cache.image.width() - (cache.validArea.x() + | 2305 << cache.image.width() - (cache.validArea.x() + |
2420 cache.validArea.width()) | 2306 cache.validArea.width()) |
2421 << ")" << endl; | 2307 << ")" << endl; |
2422 #endif | 2308 #endif |
2423 v->update(cache.validArea.x() + cache.validArea.width(), | 2309 v->getView()->update(cache.validArea.x() + cache.validArea.width(), |
2424 0, | 2310 0, |
2425 cache.image.width() - (cache.validArea.x() + | 2311 cache.image.width() - (cache.validArea.x() + |
2426 cache.validArea.width()), | 2312 cache.validArea.width()), |
2427 h); | 2313 h); |
2428 } | 2314 } |
2429 } else { | 2315 } else { |
2430 // overallMagChanged | 2316 // overallMagChanged |
2431 cerr << "\noverallMagChanged - updating all\n" << endl; | 2317 cerr << "\noverallMagChanged - updating all\n" << endl; |
2432 cache.validArea = QRect(); | 2318 cache.validArea = QRect(); |
2433 v->update(); | 2319 v->getView()->update(); |
2434 } | 2320 } |
2435 } | 2321 } |
2436 | 2322 |
2437 illuminateLocalFeatures(v, paint); | 2323 illuminateLocalFeatures(v, paint); |
2438 | 2324 |
2439 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2325 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2440 SVDEBUG << "SpectrogramLayer::paint() returning" << endl; | 2326 cerr << "SpectrogramLayer::paint() returning" << endl; |
2441 #endif | 2327 #endif |
2442 | 2328 |
2443 if (!m_synchronous) { | 2329 if (!m_synchronous) { |
2444 m_lastPaintBlockWidth = paintBlockWidth; | 2330 m_lastPaintBlockWidth = paintBlockWidth; |
2445 (void)gettimeofday(&tv, 0); | 2331 (void)gettimeofday(&tv, 0); |
2446 m_lastPaintTime = RealTime::fromTimeval(tv) - mainPaintStart; | 2332 m_lastPaintTime = RealTime::fromTimeval(tv) - mainPaintStart; |
2447 } | 2333 } |
2448 | |
2449 //!!! if (fftSuspended) fft->resume(); | |
2450 } | 2334 } |
2451 | 2335 |
2452 bool | 2336 bool |
2453 SpectrogramLayer::paintDrawBufferPeakFrequencies(View *v, | 2337 SpectrogramLayer::paintDrawBufferPeakFrequencies(LayerGeometryProvider *v, |
2454 int w, | 2338 int w, |
2455 int h, | 2339 int h, |
2456 const vector<int> &binforx, | 2340 const vector<int> &binforx, |
2457 int minbin, | 2341 int minbin, |
2458 int maxbin, | 2342 int maxbin, |
2512 if (sx != psx) { | 2396 if (sx != psx) { |
2513 peakfreqs = fft->getPeakFrequencies(FFTModel::AllPeaks, sx, | 2397 peakfreqs = fft->getPeakFrequencies(FFTModel::AllPeaks, sx, |
2514 minbin, maxbin - 1); | 2398 minbin, maxbin - 1); |
2515 if (m_colourScale == PhaseColourScale) { | 2399 if (m_colourScale == PhaseColourScale) { |
2516 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); | 2400 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); |
2517 } else if (m_normalizeColumns) { | 2401 } else if (m_normalization == NormalizeColumns) { |
2518 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); | 2402 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); |
2519 } else if (m_normalizeHybrid) { | 2403 } else if (m_normalization == NormalizeHybrid) { |
2520 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); | 2404 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); |
2521 double max = fft->getMaximumMagnitudeAt(sx); | 2405 double max = fft->getMaximumMagnitudeAt(sx); |
2522 if (max > 0.f) { | 2406 if (max > 0.f) { |
2523 for (int i = minbin; i <= maxbin; ++i) { | 2407 for (int i = minbin; i <= maxbin; ++i) { |
2524 values[i - minbin] = float(values[i - minbin] * log10(max)); | 2408 values[i - minbin] = float(values[i - minbin] * log10(max)); |
2540 if (bin > maxbin) break; | 2424 if (bin > maxbin) break; |
2541 | 2425 |
2542 double value = values[bin - minbin]; | 2426 double value = values[bin - minbin]; |
2543 | 2427 |
2544 if (m_colourScale != PhaseColourScale) { | 2428 if (m_colourScale != PhaseColourScale) { |
2545 if (!m_normalizeColumns && !m_normalizeHybrid) { | 2429 if (m_normalization != NormalizeColumns) { |
2546 value /= (m_fftSize/2.0); | 2430 value /= (m_fftSize/2.0); |
2547 } | 2431 } |
2548 mag.sample(float(value)); | 2432 mag.sample(float(value)); |
2549 value *= m_gain; | 2433 value *= m_gain; |
2550 } | 2434 } |
2576 | 2460 |
2577 return true; | 2461 return true; |
2578 } | 2462 } |
2579 | 2463 |
2580 bool | 2464 bool |
2581 SpectrogramLayer::paintDrawBuffer(View *v, | 2465 SpectrogramLayer::paintDrawBuffer(LayerGeometryProvider *v, |
2582 int w, | 2466 int w, |
2583 int h, | 2467 int h, |
2584 const vector<int> &binforx, | 2468 const vector<int> &binforx, |
2585 const vector<double> &binfory, | 2469 const vector<double> &binfory, |
2586 bool usePeaksCache, | 2470 bool usePeaksCache, |
2675 MagnitudeRange mag; | 2559 MagnitudeRange mag; |
2676 | 2560 |
2677 if (sx != psx) { | 2561 if (sx != psx) { |
2678 if (fft) { | 2562 if (fft) { |
2679 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2563 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2680 SVDEBUG << "Retrieving column " << sx << " from fft directly" << endl; | 2564 cerr << "Retrieving column " << sx << " from fft directly" << endl; |
2681 #endif | 2565 #endif |
2682 if (m_colourScale == PhaseColourScale) { | 2566 if (m_colourScale == PhaseColourScale) { |
2683 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2567 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2684 } else if (m_normalizeColumns) { | 2568 } else if (m_normalization == NormalizeColumns) { |
2685 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2569 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2686 } else if (m_normalizeHybrid) { | 2570 } else if (m_normalization == NormalizeHybrid) { |
2687 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2571 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2688 double max = fft->getMaximumMagnitudeAt(sx); | 2572 float max = fft->getMaximumMagnitudeAt(sx); |
2573 float scale = log10f(max + 1.f); | |
2574 cout << "sx = " << sx << ", max = " << max << ", log10(max) = " << log10(max) << ", scale = " << scale << endl; | |
2689 for (int i = minbin; i <= maxbin; ++i) { | 2575 for (int i = minbin; i <= maxbin; ++i) { |
2690 if (max > 0.0) { | 2576 autoarray[i - minbin] *= scale; |
2691 autoarray[i - minbin] = float(autoarray[i - minbin] * log10(max)); | |
2692 } | |
2693 } | 2577 } |
2694 } else { | 2578 } else { |
2695 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); | 2579 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); |
2696 } | 2580 } |
2697 } else { | 2581 } else { |
2698 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2582 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2699 SVDEBUG << "Retrieving column " << sx << " from peaks cache" << endl; | 2583 cerr << "Retrieving column " << sx << " from peaks cache" << endl; |
2700 #endif | 2584 #endif |
2701 c = sourceModel->getColumn(sx); | 2585 c = sourceModel->getColumn(sx); |
2702 if (m_normalizeColumns || m_normalizeHybrid) { | 2586 if (m_normalization == NormalizeColumns || |
2587 m_normalization == NormalizeHybrid) { | |
2703 for (int y = 0; y < h; ++y) { | 2588 for (int y = 0; y < h; ++y) { |
2704 if (c[y] > columnMax) columnMax = c[y]; | 2589 if (c[y] > columnMax) columnMax = c[y]; |
2705 } | 2590 } |
2706 } | 2591 } |
2707 values = c.constData() + minbin; | 2592 values = c.constData() + minbin; |
2740 } | 2625 } |
2741 if (v0 == 0.0 && v1 == 0.0) continue; | 2626 if (v0 == 0.0 && v1 == 0.0) continue; |
2742 value = prop * v0 + (1.0 - prop) * v1; | 2627 value = prop * v0 + (1.0 - prop) * v1; |
2743 | 2628 |
2744 if (m_colourScale != PhaseColourScale) { | 2629 if (m_colourScale != PhaseColourScale) { |
2745 if (!m_normalizeColumns) { | 2630 if (m_normalization != NormalizeColumns && |
2631 m_normalization != NormalizeHybrid) { | |
2746 value /= (m_fftSize/2.0); | 2632 value /= (m_fftSize/2.0); |
2747 } | 2633 } |
2748 mag.sample(float(value)); | 2634 mag.sample(float(value)); |
2749 value *= m_gain; | 2635 value *= m_gain; |
2750 } | 2636 } |
2765 value < values[bin-minbin-1] || | 2651 value < values[bin-minbin-1] || |
2766 value < values[bin-minbin+1]) continue; | 2652 value < values[bin-minbin+1]) continue; |
2767 } | 2653 } |
2768 | 2654 |
2769 if (m_colourScale != PhaseColourScale) { | 2655 if (m_colourScale != PhaseColourScale) { |
2770 if (!m_normalizeColumns) { | 2656 if (m_normalization != NormalizeColumns && |
2657 m_normalization != NormalizeHybrid) { | |
2771 value /= (m_fftSize/2.0); | 2658 value /= (m_fftSize/2.0); |
2772 } | 2659 } |
2773 mag.sample(float(value)); | 2660 mag.sample(float(value)); |
2774 value *= m_gain; | 2661 value *= m_gain; |
2775 } | 2662 } |
2799 for (int y = 0; y < h; ++y) { | 2686 for (int y = 0; y < h; ++y) { |
2800 | 2687 |
2801 double peak = peaks[y]; | 2688 double peak = peaks[y]; |
2802 | 2689 |
2803 if (m_colourScale != PhaseColourScale && | 2690 if (m_colourScale != PhaseColourScale && |
2804 (m_normalizeColumns || m_normalizeHybrid) && | 2691 (m_normalization == NormalizeColumns || |
2692 m_normalization == NormalizeHybrid) && | |
2805 columnMax > 0.f) { | 2693 columnMax > 0.f) { |
2806 peak /= columnMax; | 2694 peak /= columnMax; |
2807 if (m_normalizeHybrid) { | 2695 if (m_normalization == NormalizeHybrid) { |
2808 peak *= log10(columnMax); | 2696 peak *= log10(columnMax + 1.f); |
2809 } | 2697 } |
2810 } | 2698 } |
2811 | 2699 |
2812 unsigned char peakpix = getDisplayValue(v, peak); | 2700 unsigned char peakpix = getDisplayValue(v, peak); |
2813 | 2701 |
2817 | 2705 |
2818 return true; | 2706 return true; |
2819 } | 2707 } |
2820 | 2708 |
2821 void | 2709 void |
2822 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const | 2710 SpectrogramLayer::illuminateLocalFeatures(LayerGeometryProvider *v, QPainter &paint) const |
2823 { | 2711 { |
2824 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); | 2712 Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); |
2825 | 2713 |
2826 QPoint localPos; | 2714 QPoint localPos; |
2827 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { | 2715 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { |
2856 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1); | 2744 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1); |
2857 } | 2745 } |
2858 } | 2746 } |
2859 | 2747 |
2860 double | 2748 double |
2861 SpectrogramLayer::getYForFrequency(const View *v, double frequency) const | 2749 SpectrogramLayer::getYForFrequency(const LayerGeometryProvider *v, double frequency) const |
2862 { | 2750 { |
2863 return v->getYForFrequency(frequency, | 2751 return v->getYForFrequency(frequency, |
2864 getEffectiveMinFrequency(), | 2752 getEffectiveMinFrequency(), |
2865 getEffectiveMaxFrequency(), | 2753 getEffectiveMaxFrequency(), |
2866 m_frequencyScale == LogFrequencyScale); | 2754 m_frequencyScale == LogFrequencyScale); |
2867 } | 2755 } |
2868 | 2756 |
2869 double | 2757 double |
2870 SpectrogramLayer::getFrequencyForY(const View *v, int y) const | 2758 SpectrogramLayer::getFrequencyForY(const LayerGeometryProvider *v, int y) const |
2871 { | 2759 { |
2872 return v->getFrequencyForY(y, | 2760 return v->getFrequencyForY(y, |
2873 getEffectiveMinFrequency(), | 2761 getEffectiveMinFrequency(), |
2874 getEffectiveMaxFrequency(), | 2762 getEffectiveMaxFrequency(), |
2875 m_frequencyScale == LogFrequencyScale); | 2763 m_frequencyScale == LogFrequencyScale); |
2876 } | 2764 } |
2877 | 2765 |
2878 int | 2766 int |
2879 SpectrogramLayer::getCompletion(View *v) const | 2767 SpectrogramLayer::getCompletion(LayerGeometryProvider *v) const |
2880 { | 2768 { |
2881 if (m_updateTimer == 0) return 100; | 2769 const View *view = v->getView(); |
2882 if (m_fftModels.find(v) == m_fftModels.end()) return 100; | 2770 |
2883 | 2771 if (m_fftModels.find(view) == m_fftModels.end()) return 100; |
2884 int completion = m_fftModels[v].first->getCompletion(); | 2772 |
2885 #ifdef DEBUG_SPECTROGRAM_REPAINT | 2773 int completion = m_fftModels[view]->getCompletion(); |
2886 SVDEBUG << "SpectrogramLayer::getCompletion: completion = " << completion << endl; | 2774 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2775 cerr << "SpectrogramLayer::getCompletion: completion = " << completion << endl; | |
2887 #endif | 2776 #endif |
2888 return completion; | 2777 return completion; |
2889 } | 2778 } |
2890 | 2779 |
2891 QString | 2780 QString |
2892 SpectrogramLayer::getError(View *v) const | 2781 SpectrogramLayer::getError(LayerGeometryProvider *v) const |
2893 { | 2782 { |
2894 if (m_fftModels.find(v) == m_fftModels.end()) return ""; | 2783 const View *view = v->getView(); |
2895 return m_fftModels[v].first->getError(); | 2784 if (m_fftModels.find(view) == m_fftModels.end()) return ""; |
2785 return m_fftModels[view]->getError(); | |
2896 } | 2786 } |
2897 | 2787 |
2898 bool | 2788 bool |
2899 SpectrogramLayer::getValueExtents(double &min, double &max, | 2789 SpectrogramLayer::getValueExtents(double &min, double &max, |
2900 bool &logarithmic, QString &unit) const | 2790 bool &logarithmic, QString &unit) const |
2951 | 2841 |
2952 return true; | 2842 return true; |
2953 } | 2843 } |
2954 | 2844 |
2955 bool | 2845 bool |
2956 SpectrogramLayer::getYScaleValue(const View *v, int y, | 2846 SpectrogramLayer::getYScaleValue(const LayerGeometryProvider *v, int y, |
2957 double &value, QString &unit) const | 2847 double &value, QString &unit) const |
2958 { | 2848 { |
2959 value = getFrequencyForY(v, y); | 2849 value = getFrequencyForY(v, y); |
2960 unit = "Hz"; | 2850 unit = "Hz"; |
2961 return true; | 2851 return true; |
2962 } | 2852 } |
2963 | 2853 |
2964 bool | 2854 bool |
2965 SpectrogramLayer::snapToFeatureFrame(View *, | 2855 SpectrogramLayer::snapToFeatureFrame(LayerGeometryProvider *, |
2966 sv_frame_t &frame, | 2856 sv_frame_t &frame, |
2967 int &resolution, | 2857 int &resolution, |
2968 SnapType snap) const | 2858 SnapType snap) const |
2969 { | 2859 { |
2970 resolution = getWindowIncrement(); | 2860 resolution = getWindowIncrement(); |
2983 | 2873 |
2984 return true; | 2874 return true; |
2985 } | 2875 } |
2986 | 2876 |
2987 void | 2877 void |
2988 SpectrogramLayer::measureDoubleClick(View *v, QMouseEvent *e) | 2878 SpectrogramLayer::measureDoubleClick(LayerGeometryProvider *v, QMouseEvent *e) |
2989 { | 2879 { |
2990 ImageCache &cache = m_imageCaches[v]; | 2880 const View *view = v->getView(); |
2881 ImageCache &cache = m_imageCaches[view]; | |
2991 | 2882 |
2992 cerr << "cache width: " << cache.image.width() << ", height: " | 2883 cerr << "cache width: " << cache.image.width() << ", height: " |
2993 << cache.image.height() << endl; | 2884 << cache.image.height() << endl; |
2994 | 2885 |
2995 QImage image = cache.image; | 2886 QImage image = cache.image; |
2996 | 2887 |
2997 ImageRegionFinder finder; | 2888 ImageRegionFinder finder; |
2998 QRect rect = finder.findRegionExtents(&image, e->pos()); | 2889 QRect rect = finder.findRegionExtents(&image, e->pos()); |
3003 (new AddMeasurementRectCommand(this, mr)); | 2894 (new AddMeasurementRectCommand(this, mr)); |
3004 } | 2895 } |
3005 } | 2896 } |
3006 | 2897 |
3007 bool | 2898 bool |
3008 SpectrogramLayer::getCrosshairExtents(View *v, QPainter &paint, | 2899 SpectrogramLayer::getCrosshairExtents(LayerGeometryProvider *v, QPainter &paint, |
3009 QPoint cursorPos, | 2900 QPoint cursorPos, |
3010 std::vector<QRect> &extents) const | 2901 std::vector<QRect> &extents) const |
3011 { | 2902 { |
3012 QRect vertical(cursorPos.x() - 12, 0, 12, v->height()); | 2903 QRect vertical(cursorPos.x() - 12, 0, 12, v->getPaintHeight()); |
3013 extents.push_back(vertical); | 2904 extents.push_back(vertical); |
3014 | 2905 |
3015 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1); | 2906 QRect horizontal(0, cursorPos.y(), cursorPos.x(), 1); |
3016 extents.push_back(horizontal); | 2907 extents.push_back(horizontal); |
3017 | 2908 |
3026 paint.fontMetrics().width("C#10+50c") + 2, | 2917 paint.fontMetrics().width("C#10+50c") + 2, |
3027 paint.fontMetrics().height()); | 2918 paint.fontMetrics().height()); |
3028 extents.push_back(pitch); | 2919 extents.push_back(pitch); |
3029 | 2920 |
3030 QRect rt(cursorPos.x(), | 2921 QRect rt(cursorPos.x(), |
3031 v->height() - paint.fontMetrics().height() - 2, | 2922 v->getPaintHeight() - paint.fontMetrics().height() - 2, |
3032 paint.fontMetrics().width("1234.567 s"), | 2923 paint.fontMetrics().width("1234.567 s"), |
3033 paint.fontMetrics().height()); | 2924 paint.fontMetrics().height()); |
3034 extents.push_back(rt); | 2925 extents.push_back(rt); |
3035 | 2926 |
3036 int w(paint.fontMetrics().width("1234567890") + 2); | 2927 int w(paint.fontMetrics().width("1234567890") + 2); |
3037 QRect frame(cursorPos.x() - w - 2, | 2928 QRect frame(cursorPos.x() - w - 2, |
3038 v->height() - paint.fontMetrics().height() - 2, | 2929 v->getPaintHeight() - paint.fontMetrics().height() - 2, |
3039 w, | 2930 w, |
3040 paint.fontMetrics().height()); | 2931 paint.fontMetrics().height()); |
3041 extents.push_back(frame); | 2932 extents.push_back(frame); |
3042 | 2933 |
3043 return true; | 2934 return true; |
3044 } | 2935 } |
3045 | 2936 |
3046 void | 2937 void |
3047 SpectrogramLayer::paintCrosshairs(View *v, QPainter &paint, | 2938 SpectrogramLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, |
3048 QPoint cursorPos) const | 2939 QPoint cursorPos) const |
3049 { | 2940 { |
3050 paint.save(); | 2941 paint.save(); |
3051 | 2942 |
3052 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint); | 2943 int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint); |
3057 paint.setFont(fn); | 2948 paint.setFont(fn); |
3058 } | 2949 } |
3059 paint.setPen(m_crosshairColour); | 2950 paint.setPen(m_crosshairColour); |
3060 | 2951 |
3061 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); | 2952 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); |
3062 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height()); | 2953 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->getPaintHeight()); |
3063 | 2954 |
3064 double fundamental = getFrequencyForY(v, cursorPos.y()); | 2955 double fundamental = getFrequencyForY(v, cursorPos.y()); |
3065 | 2956 |
3066 v->drawVisibleText(paint, | 2957 v->drawVisibleText(paint, |
3067 sw + 2, | 2958 sw + 2, |
3082 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); | 2973 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); |
3083 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); | 2974 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); |
3084 QString frameLabel = QString("%1").arg(frame); | 2975 QString frameLabel = QString("%1").arg(frame); |
3085 v->drawVisibleText(paint, | 2976 v->drawVisibleText(paint, |
3086 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, | 2977 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, |
3087 v->height() - 2, | 2978 v->getPaintHeight() - 2, |
3088 frameLabel, | 2979 frameLabel, |
3089 View::OutlinedText); | 2980 View::OutlinedText); |
3090 v->drawVisibleText(paint, | 2981 v->drawVisibleText(paint, |
3091 cursorPos.x() + 2, | 2982 cursorPos.x() + 2, |
3092 v->height() - 2, | 2983 v->getPaintHeight() - 2, |
3093 rtLabel, | 2984 rtLabel, |
3094 View::OutlinedText); | 2985 View::OutlinedText); |
3095 | 2986 |
3096 int harmonic = 2; | 2987 int harmonic = 2; |
3097 | 2988 |
3098 while (harmonic < 100) { | 2989 while (harmonic < 100) { |
3099 | 2990 |
3100 int hy = int(lrint(getYForFrequency(v, fundamental * harmonic))); | 2991 int hy = int(lrint(getYForFrequency(v, fundamental * harmonic))); |
3101 if (hy < 0 || hy > v->height()) break; | 2992 if (hy < 0 || hy > v->getPaintHeight()) break; |
3102 | 2993 |
3103 int len = 7; | 2994 int len = 7; |
3104 | 2995 |
3105 if (harmonic % 2 == 0) { | 2996 if (harmonic % 2 == 0) { |
3106 if (harmonic % 4 == 0) { | 2997 if (harmonic % 4 == 0) { |
3120 | 3011 |
3121 paint.restore(); | 3012 paint.restore(); |
3122 } | 3013 } |
3123 | 3014 |
3124 QString | 3015 QString |
3125 SpectrogramLayer::getFeatureDescription(View *v, QPoint &pos) const | 3016 SpectrogramLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const |
3126 { | 3017 { |
3127 int x = pos.x(); | 3018 int x = pos.x(); |
3128 int y = pos.y(); | 3019 int y = pos.y(); |
3129 | 3020 |
3130 if (!m_model || !m_model->isOK()) return ""; | 3021 if (!m_model || !m_model->isOK()) return ""; |
3242 | 3133 |
3243 return cw; | 3134 return cw; |
3244 } | 3135 } |
3245 | 3136 |
3246 int | 3137 int |
3247 SpectrogramLayer::getVerticalScaleWidth(View *, bool detailed, QPainter &paint) const | 3138 SpectrogramLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool detailed, QPainter &paint) const |
3248 { | 3139 { |
3249 if (!m_model || !m_model->isOK()) return 0; | 3140 if (!m_model || !m_model->isOK()) return 0; |
3250 | 3141 |
3251 int cw = 0; | 3142 int cw = 0; |
3252 if (detailed) cw = getColourScaleWidth(paint); | 3143 if (detailed) cw = getColourScaleWidth(paint); |
3263 | 3154 |
3264 return cw + tickw + tw + 13; | 3155 return cw + tickw + tw + 13; |
3265 } | 3156 } |
3266 | 3157 |
3267 void | 3158 void |
3268 SpectrogramLayer::paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const | 3159 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const |
3269 { | 3160 { |
3270 if (!m_model || !m_model->isOK()) { | 3161 if (!m_model || !m_model->isOK()) { |
3271 return; | 3162 return; |
3272 } | 3163 } |
3273 | 3164 |
3377 | 3268 |
3378 paint.drawLine(cw + 7, 0, cw + 7, h); | 3269 paint.drawLine(cw + 7, 0, cw + 7, h); |
3379 | 3270 |
3380 int bin = -1; | 3271 int bin = -1; |
3381 | 3272 |
3382 for (int y = 0; y < v->height(); ++y) { | 3273 for (int y = 0; y < v->getPaintHeight(); ++y) { |
3383 | 3274 |
3384 double q0, q1; | 3275 double q0, q1; |
3385 if (!getYBinRange(v, v->height() - y, q0, q1)) continue; | 3276 if (!getYBinRange(v, v->getPaintHeight() - y, q0, q1)) continue; |
3386 | 3277 |
3387 int vy; | 3278 int vy; |
3388 | 3279 |
3389 if (int(q0) > bin) { | 3280 if (int(q0) > bin) { |
3390 vy = y; | 3281 vy = y; |
3594 if (!m_model) return 0; | 3485 if (!m_model) return 0; |
3595 return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize); | 3486 return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize); |
3596 } | 3487 } |
3597 | 3488 |
3598 void | 3489 void |
3599 SpectrogramLayer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const | 3490 SpectrogramLayer::updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const |
3600 { | 3491 { |
3601 int y0 = 0; | 3492 int y0 = 0; |
3602 if (r.startY > 0.0) y0 = int(getYForFrequency(v, r.startY)); | 3493 if (r.startY > 0.0) y0 = int(getYForFrequency(v, r.startY)); |
3603 | 3494 |
3604 int y1 = y0; | 3495 int y1 = y0; |
3608 | 3499 |
3609 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0); | 3500 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0); |
3610 } | 3501 } |
3611 | 3502 |
3612 void | 3503 void |
3613 SpectrogramLayer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const | 3504 SpectrogramLayer::setMeasureRectYCoord(LayerGeometryProvider *v, MeasureRect &r, bool start, int y) const |
3614 { | 3505 { |
3615 if (start) { | 3506 if (start) { |
3616 r.startY = getFrequencyForY(v, y); | 3507 r.startY = getFrequencyForY(v, y); |
3617 r.endY = r.startY; | 3508 r.endY = r.startY; |
3618 } else { | 3509 } else { |
3655 .arg(m_binDisplay); | 3546 .arg(m_binDisplay); |
3656 | 3547 |
3657 s += QString("normalizeColumns=\"%1\" " | 3548 s += QString("normalizeColumns=\"%1\" " |
3658 "normalizeVisibleArea=\"%2\" " | 3549 "normalizeVisibleArea=\"%2\" " |
3659 "normalizeHybrid=\"%3\" ") | 3550 "normalizeHybrid=\"%3\" ") |
3660 .arg(m_normalizeColumns ? "true" : "false") | 3551 .arg(m_normalization == NormalizeColumns ? "true" : "false") |
3661 .arg(m_normalizeVisibleArea ? "true" : "false") | 3552 .arg(m_normalization == NormalizeVisibleArea ? "true" : "false") |
3662 .arg(m_normalizeHybrid ? "true" : "false"); | 3553 .arg(m_normalization == NormalizeHybrid ? "true" : "false"); |
3663 | 3554 |
3664 Layer::toXml(stream, indent, extraAttributes + " " + s); | 3555 Layer::toXml(stream, indent, extraAttributes + " " + s); |
3665 } | 3556 } |
3666 | 3557 |
3667 void | 3558 void |
3725 attributes.value("binDisplay").toInt(&ok); | 3616 attributes.value("binDisplay").toInt(&ok); |
3726 if (ok) setBinDisplay(binDisplay); | 3617 if (ok) setBinDisplay(binDisplay); |
3727 | 3618 |
3728 bool normalizeColumns = | 3619 bool normalizeColumns = |
3729 (attributes.value("normalizeColumns").trimmed() == "true"); | 3620 (attributes.value("normalizeColumns").trimmed() == "true"); |
3730 setNormalizeColumns(normalizeColumns); | 3621 if (normalizeColumns) { |
3622 setNormalization(NormalizeColumns); | |
3623 } | |
3731 | 3624 |
3732 bool normalizeVisibleArea = | 3625 bool normalizeVisibleArea = |
3733 (attributes.value("normalizeVisibleArea").trimmed() == "true"); | 3626 (attributes.value("normalizeVisibleArea").trimmed() == "true"); |
3734 setNormalizeVisibleArea(normalizeVisibleArea); | 3627 if (normalizeVisibleArea) { |
3628 setNormalization(NormalizeVisibleArea); | |
3629 } | |
3735 | 3630 |
3736 bool normalizeHybrid = | 3631 bool normalizeHybrid = |
3737 (attributes.value("normalizeHybrid").trimmed() == "true"); | 3632 (attributes.value("normalizeHybrid").trimmed() == "true"); |
3738 setNormalizeHybrid(normalizeHybrid); | 3633 if (normalizeHybrid) { |
3739 } | 3634 setNormalization(NormalizeHybrid); |
3740 | 3635 } |
3636 } | |
3637 |