comparison layer/SpectrogramLayer.cpp @ 215:d2334a77db73

* Update to use new vamp-hostsdk instead of vamp-sdk * Make spectrogram adapt its paint block size depending on how long it actually takes to draw * Some thread debugging infrastructure
author Chris Cannam
date Fri, 02 Mar 2007 13:01:41 +0000
parents 748985c7e2c1
children 34bbbcb3c01f
comparison
equal deleted inserted replaced
214:8520b7918104 215:d2334a77db73
46 m_windowType(HanningWindow), 46 m_windowType(HanningWindow),
47 m_windowHopLevel(2), 47 m_windowHopLevel(2),
48 m_zeroPadLevel(0), 48 m_zeroPadLevel(0),
49 m_fftSize(1024), 49 m_fftSize(1024),
50 m_gain(1.0), 50 m_gain(1.0),
51 m_initialGain(1.0),
51 m_threshold(0.0), 52 m_threshold(0.0),
53 m_initialThreshold(0.0),
52 m_colourRotation(0), 54 m_colourRotation(0),
55 m_initialRotation(0),
53 m_minFrequency(10), 56 m_minFrequency(10),
54 m_maxFrequency(8000), 57 m_maxFrequency(8000),
55 m_initialMaxFrequency(8000), 58 m_initialMaxFrequency(8000),
56 m_colourScale(dBColourScale), 59 m_colourScale(dBColourScale),
57 m_colourMap(0), 60 m_colourMap(0),
58 m_frequencyScale(LinearFrequencyScale), 61 m_frequencyScale(LinearFrequencyScale),
59 m_binDisplay(AllBins), 62 m_binDisplay(AllBins),
60 m_normalizeColumns(false), 63 m_normalizeColumns(false),
61 m_normalizeVisibleArea(false), 64 m_normalizeVisibleArea(false),
62 m_lastEmittedZoomStep(-1), 65 m_lastEmittedZoomStep(-1),
66 m_lastPaintBlockWidth(0),
63 m_updateTimer(0), 67 m_updateTimer(0),
64 m_candidateFillStartFrame(0), 68 m_candidateFillStartFrame(0),
65 m_exiting(false), 69 m_exiting(false),
66 m_sliceableModel(0) 70 m_sliceableModel(0)
67 { 71 {
68 if (config == MelodicRange) { 72 if (config == FullRangeDb) {
73 m_initialMaxFrequency = 0;
74 setMaxFrequency(0);
75 } else if (config == MelodicRange) {
69 setWindowSize(8192); 76 setWindowSize(8192);
70 setWindowHopLevel(4); 77 setWindowHopLevel(4);
71 // setWindowType(ParzenWindow); 78 m_initialMaxFrequency = 1500;
72 m_initialMaxFrequency = 1000; 79 setMaxFrequency(1500);
73 setMaxFrequency(1000); 80 setMinFrequency(40);
74 setColourScale(LinearColourScale); 81 setColourScale(LinearColourScale);
82 setColourMap(ColourMapper::Sunset);
83 setFrequencyScale(LogFrequencyScale);
84 m_initialGain = 20;
85 setGain(20);
75 } else if (config == MelodicPeaks) { 86 } else if (config == MelodicPeaks) {
76 setWindowSize(4096); 87 setWindowSize(4096);
77 setWindowHopLevel(5); 88 setWindowHopLevel(5);
78 // setWindowType(BlackmanWindow);
79 m_initialMaxFrequency = 2000; 89 m_initialMaxFrequency = 2000;
80 setMaxFrequency(2000); 90 setMaxFrequency(2000);
81 setMinFrequency(40); 91 setMinFrequency(40);
82 setFrequencyScale(LogFrequencyScale); 92 setFrequencyScale(LogFrequencyScale);
83 setColourScale(MeterColourScale); 93 setColourScale(LinearColourScale);
84 setBinDisplay(PeakFrequencies); 94 setBinDisplay(PeakFrequencies);
85 setNormalizeColumns(true); 95 setNormalizeColumns(true);
86 } 96 }
87 97
88 Preferences *prefs = Preferences::getInstance(); 98 Preferences *prefs = Preferences::getInstance();
211 if (name == "Gain") { 221 if (name == "Gain") {
212 222
213 *min = -50; 223 *min = -50;
214 *max = 50; 224 *max = 50;
215 225
216 deft = lrint(log10(m_gain) * 20.0); 226 deft = lrintf(log10(m_initialGain) * 20.0);
217 if (deft < *min) deft = *min; 227 if (deft < *min) deft = *min;
218 if (deft > *max) deft = *max; 228 if (deft > *max) deft = *max;
219 229
220 } else if (name == "Threshold") { 230 } else if (name == "Threshold") {
221 231
222 *min = -50; 232 *min = -50;
223 *max = 0; 233 *max = 0;
224 234
225 deft = lrintf(AudioLevel::multiplier_to_dB(m_threshold)); 235 deft = lrintf(AudioLevel::multiplier_to_dB(m_initialThreshold));
226 if (deft < *min) deft = *min; 236 if (deft < *min) deft = *min;
227 if (deft > *max) deft = *max; 237 if (deft > *max) deft = *max;
228 238
229 } else if (name == "Colour Rotation") { 239 } else if (name == "Colour Rotation") {
230 240
231 *min = 0; 241 *min = 0;
232 *max = 256; 242 *max = 256;
233 243
234 deft = m_colourRotation; 244 deft = m_initialRotation;
235 245
236 } else if (name == "Colour Scale") { 246 } else if (name == "Colour Scale") {
237 247
238 *min = 0; 248 *min = 0;
239 *max = 4; 249 *max = 4;
343 if (name == "Colour Scale") { 353 if (name == "Colour Scale") {
344 switch (value) { 354 switch (value) {
345 default: 355 default:
346 case 0: return tr("Linear"); 356 case 0: return tr("Linear");
347 case 1: return tr("Meter"); 357 case 1: return tr("Meter");
348 case 2: return tr("dB"); 358 case 2: return tr("dBV^2");
349 case 3: return tr("dB^2"); 359 case 3: return tr("dBV");
350 case 4: return tr("Phase"); 360 case 4: return tr("Phase");
351 } 361 }
352 } 362 }
353 if (name == "Window Size") { 363 if (name == "Window Size") {
354 return QString("%1").arg(32 << value); 364 return QString("%1").arg(32 << value);
487 } else if (name == "Colour Scale") { 497 } else if (name == "Colour Scale") {
488 switch (value) { 498 switch (value) {
489 default: 499 default:
490 case 0: setColourScale(LinearColourScale); break; 500 case 0: setColourScale(LinearColourScale); break;
491 case 1: setColourScale(MeterColourScale); break; 501 case 1: setColourScale(MeterColourScale); break;
492 case 2: setColourScale(dBColourScale); break; 502 case 2: setColourScale(dBSquaredColourScale); break;
493 case 3: setColourScale(dBSquaredColourScale); break; 503 case 3: setColourScale(dBColourScale); break;
494 case 4: setColourScale(PhaseColourScale); break; 504 case 4: setColourScale(PhaseColourScale); break;
495 } 505 }
496 } else if (name == "Frequency Scale") { 506 } else if (name == "Frequency Scale") {
497 switch (value) { 507 switch (value) {
498 default: 508 default:
1082 min = m_viewMags[v].getMin(); 1092 min = m_viewMags[v].getMin();
1083 max = m_viewMags[v].getMax(); 1093 max = m_viewMags[v].getMax();
1084 } else if (!m_normalizeColumns) { 1094 } else if (!m_normalizeColumns) {
1085 if (m_colourScale == LinearColourScale || 1095 if (m_colourScale == LinearColourScale ||
1086 m_colourScale == MeterColourScale) { 1096 m_colourScale == MeterColourScale) {
1087 max = 0.1f; 1097 // max = 0.1f;
1088 } 1098 }
1089 } 1099 }
1090 1100
1091 float thresh = -80.f; 1101 float thresh = -80.f;
1092 1102
1102 1112
1103 case MeterColourScale: 1113 case MeterColourScale:
1104 value = AudioLevel::multiplier_to_preview 1114 value = AudioLevel::multiplier_to_preview
1105 ((input - min) / (max - min), 254) + 1; 1115 ((input - min) / (max - min), 254) + 1;
1106 break; 1116 break;
1107
1108 case dBColourScale:
1109 //!!! experiment with normalizing the visible area this way.
1110 //In any case, we need to have some indication of what the dB
1111 //scale is relative to.
1112 input = input / max;
1113 if (input > 0.f) {
1114 input = 10.f * log10f(input);
1115 } else {
1116 input = thresh;
1117 }
1118 if (min > 0.f) {
1119 thresh = 10.f * log10f(min);
1120 if (thresh < -80.f) thresh = -80.f;
1121 }
1122 input = (input - thresh) / (-thresh);
1123 if (input < 0.f) input = 0.f;
1124 if (input > 1.f) input = 1.f;
1125 value = int(input * 255.f) + 1;
1126 break;
1127 1117
1128 case dBSquaredColourScale: 1118 case dBSquaredColourScale:
1129 input = (input * input) / (max * max); 1119 input = ((input - min) * (input - min)) / ((max - min) * (max - min));
1130 if (input > 0.f) { 1120 if (input > 0.f) {
1131 input = 10.f * log10f(input); 1121 input = 10.f * log10f(input);
1132 } else { 1122 } else {
1133 input = thresh; 1123 input = thresh;
1134 } 1124 }
1140 if (input < 0.f) input = 0.f; 1130 if (input < 0.f) input = 0.f;
1141 if (input > 1.f) input = 1.f; 1131 if (input > 1.f) input = 1.f;
1142 value = int(input * 255.f) + 1; 1132 value = int(input * 255.f) + 1;
1143 break; 1133 break;
1144 1134
1135 case dBColourScale:
1136 //!!! experiment with normalizing the visible area this way.
1137 //In any case, we need to have some indication of what the dB
1138 //scale is relative to.
1139 input = (input - min) / (max - min);
1140 if (input > 0.f) {
1141 input = 10.f * log10f(input);
1142 } else {
1143 input = thresh;
1144 }
1145 if (min > 0.f) {
1146 thresh = 10.f * log10f(min);
1147 if (thresh < -80.f) thresh = -80.f;
1148 }
1149 input = (input - thresh) / (-thresh);
1150 if (input < 0.f) input = 0.f;
1151 if (input > 1.f) input = 1.f;
1152 value = int(input * 255.f) + 1;
1153 break;
1154
1145 case PhaseColourScale: 1155 case PhaseColourScale:
1146 value = int((input * 127.0 / M_PI) + 128); 1156 value = int((input * 127.0 / M_PI) + 128);
1147 break; 1157 break;
1148 } 1158 }
1149 1159
1172 case MeterColourScale: 1182 case MeterColourScale:
1173 input = AudioLevel::preview_to_multiplier(value - 1, 255) 1183 input = AudioLevel::preview_to_multiplier(value - 1, 255)
1174 / (m_normalizeColumns ? 1.0 : 50.0); 1184 / (m_normalizeColumns ? 1.0 : 50.0);
1175 break; 1185 break;
1176 1186
1177 case dBColourScale: 1187 case dBSquaredColourScale:
1178 input = float(value - 1) / 255.0; 1188 input = float(value - 1) / 255.0;
1179 input = (input * 80.0) - 80.0; 1189 input = (input * 80.0) - 80.0;
1180 input = powf(10.0, input) / 20.0; 1190 input = powf(10.0, input) / 20.0;
1181 value = int(input); 1191 value = int(input);
1182 break; 1192 break;
1183 1193
1184 case dBSquaredColourScale: 1194 case dBColourScale:
1185 input = float(value - 1) / 255.0; 1195 input = float(value - 1) / 255.0;
1186 input = (input * 80.0) - 80.0; 1196 input = (input * 80.0) - 80.0;
1187 input = powf(10.0, input) / 20.0; 1197 input = powf(10.0, input) / 20.0;
1188 value = int(input); 1198 value = int(input);
1189 break; 1199 break;
1844 if (recreateWholePixmapCache) { 1854 if (recreateWholePixmapCache) {
1845 x0 = 0; 1855 x0 = 0;
1846 x1 = v->width(); 1856 x1 = v->width();
1847 } 1857 }
1848 1858
1849 //!!! This width should really depend on how fast the machine is 1859 struct timeval tv;
1850 //at redrawing the spectrogram. We could fairly easily time that, 1860 (void)gettimeofday(&tv, 0);
1851 //in this function, and adjust accordingly. The following is 1861 RealTime mainPaintStart = RealTime::fromTimeval(tv);
1852 //probably about as small as the block width should go. 1862
1853 int paintBlockWidth = (300000 / zoomLevel); 1863 int paintBlockWidth = m_lastPaintBlockWidth;
1864
1865 if (paintBlockWidth == 0) {
1866 paintBlockWidth = (300000 / zoomLevel);
1867 } else {
1868 RealTime lastTime = m_lastPaintTime;
1869 while (lastTime > RealTime::fromMilliseconds(200) &&
1870 paintBlockWidth > 50) {
1871 paintBlockWidth /= 2;
1872 lastTime = lastTime / 2;
1873 }
1874 while (lastTime < RealTime::fromMilliseconds(90) &&
1875 paintBlockWidth < 1500) {
1876 paintBlockWidth *= 2;
1877 lastTime = lastTime * 2;
1878 }
1879 }
1880
1854 if (paintBlockWidth < 20) paintBlockWidth = 20; 1881 if (paintBlockWidth < 20) paintBlockWidth = 20;
1882
1883 std::cerr << "[" << this << "]: last paint width: " << m_lastPaintBlockWidth << ", last paint time: " << m_lastPaintTime << ", new paint width: " << paintBlockWidth << std::endl;
1855 1884
1856 if (cache.validArea.width() > 0) { 1885 if (cache.validArea.width() > 0) {
1857 1886
1858 int vx0 = 0, vx1 = 0; 1887 int vx0 = 0, vx1 = 0;
1859 vx0 = cache.validArea.x(); 1888 vx0 = cache.validArea.x();
2170 2199
2171 #ifdef DEBUG_SPECTROGRAM_REPAINT 2200 #ifdef DEBUG_SPECTROGRAM_REPAINT
2172 std::cerr << "SpectrogramLayer::paint() returning" << std::endl; 2201 std::cerr << "SpectrogramLayer::paint() returning" << std::endl;
2173 #endif 2202 #endif
2174 2203
2204 m_lastPaintBlockWidth = paintBlockWidth;
2205 (void)gettimeofday(&tv, 0);
2206 m_lastPaintTime = RealTime::fromTimeval(tv) - mainPaintStart;
2207
2175 if (fftSuspended) fft->resume(); 2208 if (fftSuspended) fft->resume();
2176 } 2209 }
2177 2210
2178 void 2211 void
2179 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const 2212 SpectrogramLayer::illuminateLocalFeatures(View *v, QPainter &paint) const