changeset 159:e5879045d22b

* Pull memory cache out into its own file
author Chris Cannam
date Wed, 16 Aug 2006 14:59:09 +0000
parents 74abef65711b
children abaf3d7195ce
files data/data.pro data/fft/FFTCache.cpp data/fft/FFTCache.h data/fft/FFTDataServer.cpp data/fft/FFTMemoryCache.cpp data/fft/FFTMemoryCache.h
diffstat 6 files changed, 252 insertions(+), 221 deletions(-) [+]
line wrap: on
line diff
--- a/data/data.pro	Wed Aug 16 14:57:22 2006 +0000
+++ b/data/data.pro	Wed Aug 16 14:59:09 2006 +0000
@@ -16,6 +16,7 @@
 HEADERS += fft/FFTCache.h \
            fft/FFTDataServer.h \
            fft/FFTFileCache.h \
+           fft/FFTMemoryCache.h \
            fileio/AudioFileReader.h \
            fileio/AudioFileReaderFactory.h \
            fileio/BZipFileDevice.h \
@@ -46,9 +47,9 @@
            model/SparseValueModel.h \
            model/TextModel.h \
            model/WaveFileModel.h
-SOURCES += fft/FFTCache.cpp \
-           fft/FFTDataServer.cpp \
+SOURCES += fft/FFTDataServer.cpp \
            fft/FFTFileCache.cpp \
+           fft/FFTMemoryCache.cpp \
            fileio/AudioFileReaderFactory.cpp \
            fileio/BZipFileDevice.cpp \
            fileio/CodedAudioFileReader.cpp \
--- a/data/fft/FFTCache.cpp	Wed Aug 16 14:57:22 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-    published by the Free Software Foundation; either version 2 of the
-    License, or (at your option) any later version.  See the file
-    COPYING included with this distribution for more information.
-*/
-
-#include "FFTCache.h"
-#include "system/System.h"
-
-#include <iostream>
-
-//!!! This class is a work in progress -- it does only as much as we
-// need for the current SpectrogramLayer.  Slated for substantial
-// refactoring and extension.
-
-FFTMemoryCache::FFTMemoryCache() :
-    m_width(0),
-    m_height(0),
-    m_magnitude(0),
-    m_phase(0),
-    m_factor(0)
-{
-}
-
-FFTMemoryCache::~FFTMemoryCache()
-{
-    std::cerr << "FFTMemoryCache[" << 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
-FFTMemoryCache::resize(size_t width, size_t height)
-{
-    std::cerr << "FFTMemoryCache[" << 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
-FFTMemoryCache::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
-FFTMemoryCache::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
-FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
-{
-    float max = 0.0;
-
-    for (size_t y = 0; y < m_height; ++y) {
-        float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
-        float phase = atan2f(imags[y], reals[y]);
-        phase = princargf(phase);
-        reals[y] = mag;
-        imags[y] = phase;
-        if (mag > max) max = mag;
-    }
-
-    setColumnAt(x, reals, imags, max);
-}
-
--- a/data/fft/FFTCache.h	Wed Aug 16 14:57:22 2006 +0000
+++ b/data/fft/FFTCache.h	Wed Aug 16 14:59:09 2006 +0000
@@ -54,105 +54,4 @@
 };
 
 
-/**
- * For the in-memory FFT cache, we would like to cache magnitude with
- * enough resolution to have gain applied afterwards and 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 take up too much memory.  It's not
- * expected to be accurate enough to be used as input for DSP or
- * resynthesis code.
- *
- * This implies probably 16 bits for a normalized magnitude 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 FFTMemoryCache : public FFTCache
-{
-public:
-    FFTMemoryCache(); // of size zero, call resize() before using
-    virtual ~FFTMemoryCache();
-	
-    virtual size_t getWidth() const { return m_width; }
-    virtual size_t getHeight() const { return m_height; }
-	
-    virtual void resize(size_t width, size_t height);
-    virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
-    
-    virtual float getMagnitudeAt(size_t x, size_t y) const {
-        return getNormalizedMagnitudeAt(x, y) * m_factor[x];
-    }
-    
-    virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
-        return float(m_magnitude[x][y]) / 65535.0;
-    }
-    
-    virtual float getMaximumMagnitudeAt(size_t x) const {
-        return m_factor[x];
-    }
-    
-    virtual 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;
-    }
-    
-    virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
-        float mag = getMagnitudeAt(x, y);
-        float phase = getPhaseAt(x, y);
-        real = mag * cosf(phase);
-        imag = mag * sinf(phase);
-    }
-
-    virtual void setNormalizationFactor(size_t x, float factor) {
-        if (x < m_width) m_factor[x] = factor;
-    }
-    
-    virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
-         // norm factor must already be set
-        setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
-    }
-    
-    virtual 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);
-        }
-    }
-    
-    virtual 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));
-        }
-    }
-    
-    virtual bool haveSetColumnAt(size_t) const {
-        return true;
-    }
-
-    virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) {
-        setNormalizationFactor(x, factor);
-        for (size_t y = 0; y < m_height; ++y) {
-            setMagnitudeAt(x, y, mags[y]);
-            setPhaseAt(x, y, phases[y]);
-        }
-    }
-
-    virtual void setColumnAt(size_t x, float *reals, float *imags);
-
-private:
-    size_t m_width;
-    size_t m_height;
-    uint16_t **m_magnitude;
-    uint16_t **m_phase;
-    float *m_factor;
-
-    void resize(uint16_t **&, size_t, size_t);
-};
-
 #endif
--- a/data/fft/FFTDataServer.cpp	Wed Aug 16 14:57:22 2006 +0000
+++ b/data/fft/FFTDataServer.cpp	Wed Aug 16 14:59:09 2006 +0000
@@ -16,6 +16,7 @@
 #include "FFTDataServer.h"
 
 #include "FFTFileCache.h"
+#include "FFTMemoryCache.h"
 
 #include "model/DenseTimeValueModel.h"
 
@@ -487,6 +488,8 @@
                                        m_polar ? FFTFileCache::Polar :
                                                  FFTFileCache::Rectangular);
 
+//    FFTCache *cache = new FFTMemoryCache();
+
     size_t width = m_cacheWidth;
     if (c * m_cacheWidth + width > m_width) {
         width = m_width - c * m_cacheWidth;
@@ -744,6 +747,9 @@
                 m_server.m_writeMutex.lock();
                 m_server.m_condition.wait(&m_server.m_writeMutex, 10000);
                 m_server.m_writeMutex.unlock();
+#ifdef DEBUG_FFT_SERVER
+                std::cerr << "FFTDataServer(" << this << "): waited" << std::endl;
+#endif
                 if (m_server.m_exiting) return;
             }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/fft/FFTMemoryCache.cpp	Wed Aug 16 14:59:09 2006 +0000
@@ -0,0 +1,115 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "FFTMemoryCache.h"
+#include "system/System.h"
+
+#include <iostream>
+
+FFTMemoryCache::FFTMemoryCache() :
+    m_width(0),
+    m_height(0),
+    m_magnitude(0),
+    m_phase(0),
+    m_factor(0)
+{
+}
+
+FFTMemoryCache::~FFTMemoryCache()
+{
+    std::cerr << "FFTMemoryCache[" << 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
+FFTMemoryCache::resize(size_t width, size_t height)
+{
+    std::cerr << "FFTMemoryCache[" << 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_colset.resize(width);
+
+    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
+FFTMemoryCache::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
+FFTMemoryCache::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
+FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
+{
+    float max = 0.0;
+
+    for (size_t y = 0; y < m_height; ++y) {
+        float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
+        float phase = atan2f(imags[y], reals[y]);
+        phase = princargf(phase);
+        reals[y] = mag;
+        imags[y] = phase;
+        if (mag > max) max = mag;
+    }
+
+    setColumnAt(x, reals, imags, max);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/fft/FFTMemoryCache.h	Wed Aug 16 14:59:09 2006 +0000
@@ -0,0 +1,128 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _FFT_MEMORY_CACHE_H_
+#define _FFT_MEMORY_CACHE_H_
+
+#include "FFTCache.h"
+
+#include "base/ResizeableBitset.h"
+
+/**
+ * For the in-memory FFT cache, we would like to cache magnitude with
+ * enough resolution to have gain applied afterwards and 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 take up too much memory.  It's not
+ * expected to be accurate enough to be used as input for DSP or
+ * resynthesis code.
+ *
+ * This implies probably 16 bits for a normalized magnitude 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 FFTMemoryCache : public FFTCache
+{
+public:
+    FFTMemoryCache(); // of size zero, call resize() before using
+    virtual ~FFTMemoryCache();
+	
+    virtual size_t getWidth() const { return m_width; }
+    virtual size_t getHeight() const { return m_height; }
+	
+    virtual void resize(size_t width, size_t height);
+    virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
+    
+    virtual float getMagnitudeAt(size_t x, size_t y) const {
+        return getNormalizedMagnitudeAt(x, y) * m_factor[x];
+    }
+    
+    virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
+        return float(m_magnitude[x][y]) / 65535.0;
+    }
+    
+    virtual float getMaximumMagnitudeAt(size_t x) const {
+        return m_factor[x];
+    }
+    
+    virtual 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;
+    }
+    
+    virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
+        float mag = getMagnitudeAt(x, y);
+        float phase = getPhaseAt(x, y);
+        real = mag * cosf(phase);
+        imag = mag * sinf(phase);
+    }
+
+    virtual void setNormalizationFactor(size_t x, float factor) {
+        if (x < m_width) m_factor[x] = factor;
+    }
+    
+    virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
+         // norm factor must already be set
+        setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
+    }
+    
+    virtual 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);
+        }
+    }
+    
+    virtual 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));
+        }
+    }
+    
+    virtual bool haveSetColumnAt(size_t x) const {
+        return m_colset.get(x);
+    }
+
+    virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) {
+        setNormalizationFactor(x, factor);
+        for (size_t y = 0; y < m_height; ++y) {
+            setMagnitudeAt(x, y, mags[y]);
+            setPhaseAt(x, y, phases[y]);
+        }
+        m_colset.set(x);
+    }
+
+    virtual void setColumnAt(size_t x, float *reals, float *imags);
+
+private:
+    size_t m_width;
+    size_t m_height;
+    uint16_t **m_magnitude;
+    uint16_t **m_phase;
+    float *m_factor;
+    ResizeableBitset m_colset;
+
+    void resize(uint16_t **&, size_t, size_t);
+};
+
+
+#endif
+