changeset 85:d31c4f5230d7

* Start factoring out the spectrogram's FFT cache into a separate set of classes that will permit a choice of disk or memory cache strategies
author Chris Cannam
date Tue, 02 May 2006 12:27:41 +0000
parents c683705adcbf
children 93a7efc75fb7
files layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 2 files changed, 4 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Sat Apr 29 19:20:28 2006 +0000
+++ b/layer/SpectrogramLayer.cpp	Tue May 02 12:27:41 2006 +0000
@@ -20,6 +20,7 @@
 #include "base/AudioLevel.h"
 #include "base/Window.h"
 #include "base/Pitch.h"
+#include "base/FFTCache.h"
 
 #include <QPainter>
 #include <QImage>
@@ -1210,84 +1211,6 @@
     return input;
 }
 
-
-SpectrogramLayer::Cache::Cache() :
-    m_width(0),
-    m_height(0),
-    m_magnitude(0),
-    m_phase(0),
-    m_factor(0)
-{
-}
-
-SpectrogramLayer::Cache::~Cache()
-{
-    std::cerr << "SpectrogramLayer::Cache[" << this << "]::~Cache" << std::endl;
-
-    for (size_t i = 0; i < m_width; ++i) {
-	if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]);
-	if (m_phase && m_phase[i]) free(m_phase[i]);
-    }
-
-    if (m_magnitude) free(m_magnitude);
-    if (m_phase) free(m_phase);
-    if (m_factor) free(m_factor);
-}
-
-void
-SpectrogramLayer::Cache::resize(size_t width, size_t height)
-{
-    std::cerr << "SpectrogramLayer::Cache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl;
-    
-    if (m_width == width && m_height == height) return;
-
-    resize(m_magnitude, width, height);
-    resize(m_phase, width, height);
-
-    m_factor = (float *)realloc(m_factor, width * sizeof(float));
-
-    m_width = width;
-    m_height = height;
-
-    std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl;
-}
-
-void
-SpectrogramLayer::Cache::resize(uint16_t **&array, size_t width, size_t height)
-{
-    for (size_t i = width; i < m_width; ++i) {
-	free(array[i]);
-    }
-
-    if (width != m_width) {
-	array = (uint16_t **)realloc(array, width * sizeof(uint16_t *));
-	if (!array) throw std::bad_alloc();
-	MUNLOCK(array, width * sizeof(uint16_t *));
-    }
-
-    for (size_t i = m_width; i < width; ++i) {
-	array[i] = 0;
-    }
-
-    for (size_t i = 0; i < width; ++i) {
-	array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t));
-	if (!array[i]) throw std::bad_alloc();
-	MUNLOCK(array[i], height * sizeof(uint16_t));
-    }
-}
-
-void
-SpectrogramLayer::Cache::reset()
-{
-    for (size_t x = 0; x < m_width; ++x) {
-	for (size_t y = 0; y < m_height; ++y) {
-	    m_magnitude[x][y] = 0;
-	    m_phase[x][y] = 0;
-	}
-	m_factor[x] = 1.0;
-    }
-}	    
-
 void
 SpectrogramLayer::CacheFillThread::run()
 {
@@ -1356,7 +1279,7 @@
 	    size_t height = windowSize / 2;
 
 	    if (!m_layer.m_cache) {
-		m_layer.m_cache = new Cache;
+		m_layer.m_cache = new FFTMemoryCache;
 	    }
 
 	    m_layer.m_cache->resize(width, height);
--- a/layer/SpectrogramLayer.h	Sat Apr 29 19:20:28 2006 +0000
+++ b/layer/SpectrogramLayer.h	Tue May 02 12:27:41 2006 +0000
@@ -28,13 +28,12 @@
 
 #include <fftw3.h>
 
-#include <stdint.h>
-
 class View;
 class QPainter;
 class QImage;
 class QPixmap;
 class QTimer;
+class FFTCacheBase;
 
 /**
  * SpectrogramLayer represents waveform data (obtained from a
@@ -218,100 +217,9 @@
     BinDisplay          m_binDisplay;
     bool                m_normalizeColumns;
 
-    // We would like to cache magnitude in a way that can have gain
-    // applied afterwards and can determine whether something is a
-    // peak or not, and also cache phase rather than only
-    // phase-adjusted frequency so that we don't have to recalculate
-    // if switching between phase and magnitude displays.  At the same
-    // time, we don't want to waste too much memory.
-
-    // This implies probably 16 bits for a normalized magnitude (in
-    // dB?) and at most 16 bits for phase.
-
-    // Each column's magnitudes are expected to be stored normalized
-    // to [0,1] with respect to the column, so the normalization
-    // factor should be calculated before all values in a column, and
-    // set appropriately.
-
-    class Cache {
-    public:
-	Cache(); // of size zero, call resize() before using
-	~Cache();
-
-	size_t getWidth() const { return m_width; }
-	size_t getHeight() const { return m_height; }
-	
-	void resize(size_t width, size_t height);
-	void reset(); // zero-fill or 1-fill as appropriate without changing size
-	
-	float getMagnitudeAt(size_t x, size_t y) const {
-	    return getNormalizedMagnitudeAt(x, y) * m_factor[x];
-	}
-
-	float getNormalizedMagnitudeAt(size_t x, size_t y) const {
-	    return float(m_magnitude[x][y]) / 65535.0;
-	}
-
-	float getPhaseAt(size_t x, size_t y) const {
-	    int16_t i = (int16_t)m_phase[x][y];
-	    return (float(i) / 32767.0) * M_PI;
-	}
-
-	bool isLocalPeak(size_t x, size_t y) const {
-	    if (y > 0 && m_magnitude[x][y] < m_magnitude[x][y-1]) return false;
-	    if (y < m_height-1 && m_magnitude[x][y] < m_magnitude[x][y+1]) return false;
-	    return true;
-	}
-
-	bool isOverThreshold(size_t x, size_t y, float threshold) const {
-	    if (threshold == 0.0) return true;
-	    return getMagnitudeAt(x, y) > threshold;
-	}
-
-	void setNormalizationFactor(size_t x, float factor) {
-	    if (x < m_width) m_factor[x] = factor;
-	}
-
-	void setMagnitudeAt(size_t x, size_t y, float mag) {
-	    // norm factor must already be set
-	    setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
-	}
-
-	void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
-	    if (x < m_width && y < m_height) {
-		m_magnitude[x][y] = uint16_t(norm * 65535.0);
-	    }
-	}
-
-	void setPhaseAt(size_t x, size_t y, float phase) {
-	    // phase in range -pi -> pi
-	    if (x < m_width && y < m_height) {
-		m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
-	    }
-	}
-
-	QColor getColour(unsigned char index) const {
-	    return m_colours[index];
-	}
-
-	void setColour(unsigned char index, QColor colour) {
-	    m_colours[index] = colour;
-	}
-
-    private:
-	size_t m_width;
-	size_t m_height;
-	uint16_t **m_magnitude;
-	uint16_t **m_phase;
-	float *m_factor;
-	QColor m_colours[256];
-
-	void resize(uint16_t **&, size_t, size_t);
-    };
-
     enum { NO_VALUE = 0 }; // colour index for unused pixels
 
-    Cache *m_cache;
+    FFTCacheBase *m_cache;
     bool m_cacheInvalid;
 
     class CacheFillThread : public QThread