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