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