comparison layer/SpectrogramLayer.cpp @ 277:8acd30ed735c

* Fix up and simplify the LayerTreeModel, removing a horrible memory leak * Move phase-unwrapped frequency estimation from SpectrogramLayer to FFTDataServer * Make the spectrum show peak phase-unwrapped frequencies as well (still needs work) * Start adding piano keyboard horizontal scale to spectrum * Debug output for id3 tags
author Chris Cannam
date Tue, 03 Jul 2007 12:46:18 +0000
parents e954c00cbe55
children a078aa2932cc
comparison
equal deleted inserted replaced
276:21c7152ddba8 277:8acd30ed735c
1062 for (int pixel = 0; pixel < 256; ++pixel) { 1062 for (int pixel = 0; pixel < 256; ++pixel) {
1063 m_palette.setColour(pixel, newPixels[pixel]); 1063 m_palette.setColour(pixel, newPixels[pixel]);
1064 } 1064 }
1065 } 1065 }
1066 1066
1067 float
1068 SpectrogramLayer::calculateFrequency(size_t bin,
1069 size_t windowSize,
1070 size_t windowIncrement,
1071 size_t sampleRate,
1072 float oldPhase,
1073 float newPhase,
1074 bool &steadyState)
1075 {
1076 // At frequency f, phase shift of 2pi (one cycle) happens in 1/f sec.
1077 // At hopsize h and sample rate sr, one hop happens in h/sr sec.
1078 // At window size w, for bin b, f is b*sr/w.
1079 // thus 2pi phase shift happens in w/(b*sr) sec.
1080 // We need to know what phase shift we expect from h/sr sec.
1081 // -> 2pi * ((h/sr) / (w/(b*sr)))
1082 // = 2pi * ((h * b * sr) / (w * sr))
1083 // = 2pi * (h * b) / w.
1084
1085 float frequency = (float(bin) * sampleRate) / windowSize;
1086
1087 float expectedPhase =
1088 oldPhase + (2.0 * M_PI * bin * windowIncrement) / windowSize;
1089
1090 float phaseError = princargf(newPhase - expectedPhase);
1091
1092 if (fabsf(phaseError) < (1.1f * (windowIncrement * M_PI) / windowSize)) {
1093
1094 // The new frequency estimate based on the phase error
1095 // resulting from assuming the "native" frequency of this bin
1096
1097 float newFrequency =
1098 (sampleRate * (expectedPhase + phaseError - oldPhase)) /
1099 (2 * M_PI * windowIncrement);
1100
1101 steadyState = true;
1102 return newFrequency;
1103 }
1104
1105 steadyState = false;
1106 return frequency;
1107 }
1108
1109 unsigned char 1067 unsigned char
1110 SpectrogramLayer::getDisplayValue(View *v, float input) const 1068 SpectrogramLayer::getDisplayValue(View *v, float input) const
1111 { 1069 {
1112 int value; 1070 int value;
1113 1071
1361 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, 1319 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y,
1362 float &freqMin, float &freqMax, 1320 float &freqMin, float &freqMax,
1363 float &adjFreqMin, float &adjFreqMax) 1321 float &adjFreqMin, float &adjFreqMax)
1364 const 1322 const
1365 { 1323 {
1324 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1325 return false;
1326 }
1327
1366 FFTModel *fft = getFFTModel(v); 1328 FFTModel *fft = getFFTModel(v);
1367 if (!fft) return false; 1329 if (!fft) return false;
1368 1330
1369 float s0 = 0, s1 = 0; 1331 float s0 = 0, s1 = 0;
1370 if (!getXBinRange(v, x, s0, s1)) return false; 1332 if (!getXBinRange(v, x, s0, s1)) return false;
1405 float freq = binfreq; 1367 float freq = binfreq;
1406 bool steady = false; 1368 bool steady = false;
1407 1369
1408 if (s < int(fft->getWidth()) - 1) { 1370 if (s < int(fft->getWidth()) - 1) {
1409 1371
1410 freq = calculateFrequency(q, 1372 fft->estimateStableFrequency(s, q, freq);
1411 windowSize,
1412 windowIncrement,
1413 sr,
1414 fft->getPhaseAt(s, q),
1415 fft->getPhaseAt(s+1, q),
1416 steady);
1417 1373
1418 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; 1374 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq;
1419 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; 1375 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq;
1420 1376
1421 haveAdj = true; 1377 haveAdj = true;
1433 bool 1389 bool
1434 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y, 1390 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y,
1435 float &min, float &max, 1391 float &min, float &max,
1436 float &phaseMin, float &phaseMax) const 1392 float &phaseMin, float &phaseMax) const
1437 { 1393 {
1394 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1395 return false;
1396 }
1397
1438 float q0 = 0, q1 = 0; 1398 float q0 = 0, q1 = 0;
1439 if (!getYBinRange(v, y, q0, q1)) return false; 1399 if (!getYBinRange(v, y, q0, q1)) return false;
1440 1400
1441 float s0 = 0, s1 = 0; 1401 float s0 = 0, s1 = 0;
1442 if (!getXBinRange(v, x, s0, s1)) return false; 1402 if (!getXBinRange(v, x, s0, s1)) return false;
2131 if (s == s1i) sprop *= s1 - s; 2091 if (s == s1i) sprop *= s1 - s;
2132 2092
2133 if (m_binDisplay == PeakFrequencies && 2093 if (m_binDisplay == PeakFrequencies &&
2134 s < int(fft->getWidth()) - 1) { 2094 s < int(fft->getWidth()) - 1) {
2135 2095
2136 bool steady = false; 2096 float f = 0;
2137 float f = calculateFrequency(q, 2097 fft->estimateStableFrequency(s, q, f);
2138 m_windowSize,
2139 increment,
2140 sr,
2141 fft->getPhaseAt(s, q),
2142 fft->getPhaseAt(s+1, q),
2143 steady);
2144 2098
2145 y0 = y1 = v->getYForFrequency 2099 y0 = y1 = v->getYForFrequency
2146 (f, displayMinFreq, displayMaxFreq, logarithmic); 2100 (f, displayMinFreq, displayMaxFreq, logarithmic);
2147 } 2101 }
2148 2102
2853 py = vy; 2807 py = vy;
2854 } 2808 }
2855 2809
2856 if (m_frequencyScale == LogFrequencyScale) { 2810 if (m_frequencyScale == LogFrequencyScale) {
2857 2811
2812 // piano keyboard
2813
2858 paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h); 2814 paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h);
2859 2815
2860 float minf = getEffectiveMinFrequency(); 2816 float minf = getEffectiveMinFrequency();
2861 float maxf = getEffectiveMaxFrequency(); 2817 float maxf = getEffectiveMaxFrequency();
2862 2818
2877 2833
2878 if (n == 1) { 2834 if (n == 1) {
2879 // C# -- fill the C from here 2835 // C# -- fill the C from here
2880 if (ppy - y > 2) { 2836 if (ppy - y > 2) {
2881 paint.fillRect(w - pkw, 2837 paint.fillRect(w - pkw,
2882 // y - (py - y) / 2 - (py - y) / 4,
2883 y, 2838 y,
2884 pkw, 2839 pkw,
2885 (py + ppy) / 2 - y, 2840 (py + ppy) / 2 - y,
2886 // py - y + 1,
2887 Qt::gray); 2841 Qt::gray);
2888 } 2842 }
2889 } 2843 }
2890 2844
2891 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { 2845 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) {