diff 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
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Mon Jul 02 14:58:34 2007 +0000
+++ b/layer/SpectrogramLayer.cpp	Tue Jul 03 12:46:18 2007 +0000
@@ -1064,48 +1064,6 @@
     }
 }
 
-float
-SpectrogramLayer::calculateFrequency(size_t bin,
-				     size_t windowSize,
-				     size_t windowIncrement,
-				     size_t sampleRate,
-				     float oldPhase,
-				     float newPhase,
-				     bool &steadyState)
-{
-    // At frequency f, phase shift of 2pi (one cycle) happens in 1/f sec.
-    // At hopsize h and sample rate sr, one hop happens in h/sr sec.
-    // At window size w, for bin b, f is b*sr/w.
-    // thus 2pi phase shift happens in w/(b*sr) sec.
-    // We need to know what phase shift we expect from h/sr sec.
-    // -> 2pi * ((h/sr) / (w/(b*sr)))
-    //  = 2pi * ((h * b * sr) / (w * sr))
-    //  = 2pi * (h * b) / w.
-
-    float frequency = (float(bin) * sampleRate) / windowSize;
-
-    float expectedPhase =
-	oldPhase + (2.0 * M_PI * bin * windowIncrement) / windowSize;
-
-    float phaseError = princargf(newPhase - expectedPhase);
-	    
-    if (fabsf(phaseError) < (1.1f * (windowIncrement * M_PI) / windowSize)) {
-
-	// The new frequency estimate based on the phase error
-	// resulting from assuming the "native" frequency of this bin
-
-	float newFrequency =
-	    (sampleRate * (expectedPhase + phaseError - oldPhase)) /
-	    (2 * M_PI * windowIncrement);
-
-	steadyState = true;
-	return newFrequency;
-    }
-
-    steadyState = false;
-    return frequency;
-}
-
 unsigned char
 SpectrogramLayer::getDisplayValue(View *v, float input) const
 {
@@ -1363,6 +1321,10 @@
 					     float &adjFreqMin, float &adjFreqMax)
 const
 {
+    if (!m_model || !m_model->isOK() || !m_model->isReady()) {
+	return false;
+    }
+
     FFTModel *fft = getFFTModel(v);
     if (!fft) return false;
 
@@ -1407,13 +1369,7 @@
 	    
 	    if (s < int(fft->getWidth()) - 1) {
 
-		freq = calculateFrequency(q, 
-					  windowSize,
-					  windowIncrement,
-					  sr, 
-					  fft->getPhaseAt(s, q),
-					  fft->getPhaseAt(s+1, q),
-					  steady);
+                fft->estimateStableFrequency(s, q, freq);
 	    
 		if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq;
 		if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq;
@@ -1435,6 +1391,10 @@
 				      float &min, float &max,
 				      float &phaseMin, float &phaseMax) const
 {
+    if (!m_model || !m_model->isOK() || !m_model->isReady()) {
+	return false;
+    }
+
     float q0 = 0, q1 = 0;
     if (!getYBinRange(v, y, q0, q1)) return false;
 
@@ -2133,14 +2093,8 @@
 		if (m_binDisplay == PeakFrequencies &&
 		    s < int(fft->getWidth()) - 1) {
 
-		    bool steady = false;
-                    float f = calculateFrequency(q,
-						 m_windowSize,
-						 increment,
-						 sr,
-						 fft->getPhaseAt(s, q),
-						 fft->getPhaseAt(s+1, q),
-						 steady);
+                    float f = 0;
+                    fft->estimateStableFrequency(s, q, f);
 
 		    y0 = y1 = v->getYForFrequency
 			(f, displayMinFreq, displayMaxFreq, logarithmic);
@@ -2855,6 +2809,8 @@
 
     if (m_frequencyScale == LogFrequencyScale) {
 
+        // piano keyboard
+
 	paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h);
 
 	float minf = getEffectiveMinFrequency();
@@ -2879,11 +2835,9 @@
                 // C# -- fill the C from here
                 if (ppy - y > 2) {
                     paint.fillRect(w - pkw,
-//                                   y - (py - y) / 2 - (py - y) / 4, 
                                    y,
                                    pkw,
                                    (py + ppy) / 2 - y,
-//                                   py - y + 1,
                                    Qt::gray);
                 }
             }