changeset 113:7a23edd831cb

* Various fft server improvements, including the ability to pick out data from an existing fft cache at a smaller increment or larger fft size rather than recalculating it (if appropriate)
author Chris Cannam
date Thu, 29 Jun 2006 16:16:49 +0000
parents 43b1ca9647e1
children 991de8783cf5
files layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 2 files changed, 65 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Wed Jun 28 15:42:04 2006 +0000
+++ b/layer/SpectrogramLayer.cpp	Thu Jun 29 16:16:49 2006 +0000
@@ -122,22 +122,20 @@
 void
 SpectrogramLayer::getFFTServer()
 {
-    //!!! really want to check that params differ from previous ones
-
     if (m_fftServer) {
         FFTDataServer::releaseInstance(m_fftServer);
         m_fftServer = 0;
     }
 
     if (m_model) {
-        m_fftServer = FFTDataServer::getInstance(m_model,
-                                                 m_channel,
-                                                 m_windowType,
-                                                 m_windowSize,
-                                                 getWindowIncrement(),
-                                                 m_fftSize,
-                                                 true,
-                                                 m_candidateFillStartFrame);
+        m_fftServer = FFTDataServer::getFuzzyInstance(m_model,
+                                                      m_channel,
+                                                      m_windowType,
+                                                      m_windowSize,
+                                                      getWindowIncrement(),
+                                                      m_fftSize,
+                                                      true,
+                                                      m_candidateFillStartFrame);
 
         m_lastFillExtent = 0;
 
@@ -1290,21 +1288,21 @@
 	    if (q == q0i) freqMin = binfreq;
 	    if (q == q1i) freqMax = binfreq;
 
-	    if (peaksOnly && !m_fftServer->isLocalPeak(s, q)) continue;
+	    if (peaksOnly && !isFFTLocalPeak(s, q)) continue;
 
-	    if (!m_fftServer->isOverThreshold(s, q, m_threshold)) continue;
+	    if (!isFFTOverThreshold(s, q, m_threshold)) continue;
 
 	    float freq = binfreq;
 	    bool steady = false;
 	    
-	    if (s < int(m_fftServer->getWidth()) - 1) {
+	    if (s < int(getFFTWidth()) - 1) {
 
 		freq = calculateFrequency(q, 
 					  windowSize,
 					  windowIncrement,
 					  sr, 
-					  m_fftServer->getPhaseAt(s, q),
-					  m_fftServer->getPhaseAt(s+1, q),
+					  getFFTPhaseAt(s, q),
+					  getFFTPhaseAt(s+1, q),
 					  steady);
 	    
 		if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq;
@@ -1343,8 +1341,8 @@
 
     if (m_fftServer) {
 
-        int cw = m_fftServer->getWidth();
-        int ch = m_fftServer->getHeight();
+        int cw = getFFTWidth();
+        int ch = getFFTHeight();
 
         min = 0.0;
         max = 0.0;
@@ -1358,11 +1356,11 @@
                     
                     float value;
 
-                    value = m_fftServer->getPhaseAt(s, q);
+                    value = getFFTPhaseAt(s, q);
                     if (!have || value < phaseMin) { phaseMin = value; }
                     if (!have || value > phaseMax) { phaseMax = value; }
 
-                    value = m_fftServer->getMagnitudeAt(s, q);
+                    value = getFFTMagnitudeAt(s, q);
                     if (!have || value < min) { min = value; }
                     if (!have || value > max) { max = value; }
                     
@@ -1639,8 +1637,9 @@
     }
 
     //!!! quite wrong and won't work for layers that may be in more than one view
-    if (v->height() > (bins - minbin) / (m_zeroPadLevel + 1)) {
+    if (v->height() / 1.5 > (bins - minbin) / (m_zeroPadLevel + 1)) {
         if (m_zeroPadLevel != 3) {
+            std::cerr << v->height()/1.5 << " > " << ((bins - minbin) / (m_zeroPadLevel + 1)) << ": switching to smoothed display" << std::endl;
             ((SpectrogramLayer *)this)->setZeroPadLevel(3);
             return;
         }
@@ -1684,8 +1683,8 @@
 	int s0i = int(s0 + 0.001);
 	int s1i = int(s1);
 
-	if (s1i >= m_fftServer->getWidth()) {
-	    if (s0i >= m_fftServer->getWidth()) {
+	if (s1i >= getFFTWidth()) {
+	    if (s0i >= getFFTWidth()) {
 		continue;
 	    } else {
 		s1i = s0i;
@@ -1694,7 +1693,7 @@
 
         for (int s = s0i; s <= s1i; ++s) {
 
-//            if (!m_fftServer->haveSetColumnAt(s)) continue;
+            if (!isFFTColumnReady(s)) continue;
 
             for (size_t q = minbin; q < bins; ++q) {
 
@@ -1703,25 +1702,25 @@
 
 		if (m_binDisplay == PeakBins ||
 		    m_binDisplay == PeakFrequencies) {
-		    if (!m_fftServer->isLocalPeak(s, q)) continue;
+		    if (!isFFTLocalPeak(s, q)) continue;
 		}
 		
-		if (!m_fftServer->isOverThreshold(s, q, m_threshold)) continue;
+		if (!isFFTOverThreshold(s, q, m_threshold)) continue;
 
 		float sprop = 1.0;
 		if (s == s0i) sprop *= (s + 1) - s0;
 		if (s == s1i) sprop *= s1 - s;
  
 		if (m_binDisplay == PeakFrequencies &&
-		    s < int(m_fftServer->getWidth()) - 1) {
+		    s < int(getFFTWidth()) - 1) {
 
 		    bool steady = false;
                     float f = calculateFrequency(q,
 						 m_windowSize,
 						 increment,
 						 sr,
-						 m_fftServer->getPhaseAt(s, q),
-						 m_fftServer->getPhaseAt(s+1, q),
+						 getFFTPhaseAt(s, q),
+						 getFFTPhaseAt(s+1, q),
 						 steady);
 
 		    y0 = y1 = v->getYForFrequency
@@ -1734,11 +1733,11 @@
                 float value;
                 
                 if (m_colourScale == PhaseColourScale) {
-                    value = m_fftServer->getPhaseAt(s, q);
+                    value = getFFTPhaseAt(s, q);
                 } else if (m_normalizeColumns) {
-                    value = m_fftServer->getNormalizedMagnitudeAt(s, q) * m_gain;
+                    value = getFFTNormalizedMagnitudeAt(s, q) * m_gain;
                 } else {
-                    value = m_fftServer->getMagnitudeAt(s, q) * m_gain;
+                    value = getFFTMagnitudeAt(s, q) * m_gain;
                 }
 
 		for (int y = y0i; y <= y1i; ++y) {
--- a/layer/SpectrogramLayer.h	Wed Jun 28 15:42:04 2006 +0000
+++ b/layer/SpectrogramLayer.h	Thu Jun 29 16:16:49 2006 +0000
@@ -22,6 +22,7 @@
 #include "base/Thread.h"
 #include "model/PowerOfSqrtTwoZoomConstraint.h"
 #include "model/DenseTimeValueModel.h"
+#include "fileio/FFTDataServer.h"
 
 #include <QMutex>
 #include <QWaitCondition>
@@ -33,7 +34,6 @@
 class QImage;
 class QPixmap;
 class QTimer;
-class FFTDataServer;
 
 /**
  * SpectrogramLayer represents waveform data (obtained from a
@@ -308,6 +308,40 @@
         else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
         else return m_windowSize / (1 << (m_windowHopLevel - 1));
     }
+
+    size_t getFFTWidth() const {
+        return m_fftServer->getWidth(getWindowIncrement(), m_fftSize);
+    }
+    size_t getFFTHeight() const {
+        return m_fftServer->getHeight(getWindowIncrement(), m_fftSize);
+    }
+    float getFFTMagnitudeAt(size_t x, size_t y) const {
+        return m_fftServer->getMagnitudeAt(getWindowIncrement(), m_fftSize,
+                                              x, y);
+    }
+    float getFFTNormalizedMagnitudeAt(size_t x, size_t y) const {
+        return m_fftServer->getNormalizedMagnitudeAt(getWindowIncrement(), m_fftSize,
+                                                     x, y);
+    }
+    float getFFTPhaseAt(size_t x, size_t y) const {
+        return m_fftServer->getPhaseAt(getWindowIncrement(), m_fftSize,
+                                       x, y);
+    }
+    void getFFTValuesAt(size_t x, size_t y, float &real, float &imag) const {
+        m_fftServer->getValuesAt(getWindowIncrement(), m_fftSize,
+                                 x, y, real, imag);
+    }
+    bool isFFTLocalPeak(size_t x, size_t y) const {
+        return m_fftServer->isLocalPeak(getWindowIncrement(), m_fftSize,
+                                        x, y);
+    }
+    bool isFFTOverThreshold(size_t x, size_t y, float threshold) const {
+        return m_fftServer->isOverThreshold(getWindowIncrement(), m_fftSize,
+                                            x, y, threshold);
+    }
+    bool isFFTColumnReady(size_t x) const {
+        return m_fftServer->isColumnReady(getWindowIncrement(), m_fftSize, x);
+    }
 };
 
 #endif