changeset 334:aa8dbac62024

* Pass StorageAdviser::Criteria into FFTModel constructor etc
author Chris Cannam
date Sun, 11 Nov 2007 20:31:12 +0000
parents 1afaf98dbf11
children 02d2ad95ea52 5cd7f6d10d47
files base/StorageAdviser.cpp base/StorageAdviser.h data/fft/FFTDataServer.cpp data/fft/FFTDataServer.h data/fft/FFTMemoryCache.cpp data/fft/FFTMemoryCache.h data/fileio/MP3FileReader.cpp data/fileio/MP3FileReader.h data/model/FFTModel.cpp data/model/FFTModel.h plugin/transform/FeatureExtractionModelTransformer.cpp
diffstat 11 files changed, 168 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/base/StorageAdviser.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/base/StorageAdviser.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -51,7 +51,7 @@
         memoryFree = 0;
     }
 
-    std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << std::endl;
+    std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << std::endl;
 
     //!!! We have a potentially serious problem here if multiple
     //recommendations are made in advance of any of the resulting
--- a/base/StorageAdviser.h	Fri Nov 09 17:46:58 2007 +0000
+++ b/base/StorageAdviser.h	Sun Nov 11 20:31:12 2007 +0000
@@ -1,3 +1,4 @@
+
 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
 
 /*
--- a/data/fft/FFTDataServer.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fft/FFTDataServer.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -52,6 +52,7 @@
                            size_t windowIncrement,
                            size_t fftSize,
                            bool polar,
+                           StorageAdviser::Criteria criteria,
                            size_t fillFromColumn)
 {
     QString n = generateFileBasename(model,
@@ -91,6 +92,7 @@
                                    windowIncrement,
                                    fftSize,
                                    polar,
+                                   criteria,
                                    fillFromColumn);
     } catch (InsufficientDiscSpace) {
         delete server;
@@ -112,6 +114,7 @@
                                 size_t windowIncrement,
                                 size_t fftSize,
                                 bool polar,
+                                StorageAdviser::Criteria criteria,
                                 size_t fillFromColumn)
 {
     // Fuzzy matching:
@@ -217,6 +220,7 @@
                        windowIncrement,
                        fftSize,
                        polar,
+                       criteria,
                        fillFromColumn);
 }
 
@@ -479,6 +483,7 @@
 			     size_t windowIncrement,
 			     size_t fftSize,
                              bool polar,
+                             StorageAdviser::Criteria criteria,
                              size_t fillFromColumn) :
     m_fileBaseName(fileBaseName),
     m_model(model),
@@ -526,26 +531,32 @@
     m_cacheWidth = 2;
     while (bits) { m_cacheWidth <<= 1; --bits; }
 
-    //!!! Need to pass in what this server is intended for
-    // (e.g. playback processing, spectrogram, feature extraction),
-    // or pass in something akin to the storage adviser criteria.
-    // That probably goes alongside the polar argument.
-    // For now we'll assume "spectrogram" criteria for polar ffts,
-    // and "feature extraction" criteria for rectangular ones.
+    if (criteria == StorageAdviser::NoCriteria) {
 
-    StorageAdviser::Criteria criteria;
-    if (m_polar) {
-        criteria = StorageAdviser::Criteria
-            (StorageAdviser::SpeedCritical |
-             StorageAdviser::LongRetentionLikely);
-    } else {
-        criteria = StorageAdviser::Criteria
-            (StorageAdviser::PrecisionCritical);
+        // assume "spectrogram" criteria for polar ffts, and "feature
+        // extraction" criteria for rectangular ones.
+
+        if (m_polar) {
+            criteria = StorageAdviser::Criteria
+                (StorageAdviser::SpeedCritical |
+                 StorageAdviser::LongRetentionLikely);
+        } else {
+            criteria = StorageAdviser::Criteria
+                (StorageAdviser::PrecisionCritical);
+        }
     }
 
     int cells = m_width * m_height;
     int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb
     int maximumSize = (cells / 1024) * sizeof(float); // kb
+
+    // We don't have a compact rectangular representation, and compact
+    // of course is never precision-critical
+    bool canCompact = true;
+    if ((criteria & StorageAdviser::PrecisionCritical) || !m_polar) {
+        canCompact = false;
+        minimumSize = maximumSize; // don't use compact
+    }
     
     StorageAdviser::Recommendation recommendation;
 
@@ -574,24 +585,15 @@
 
     m_memoryCache = false;
 
-    if (recommendation & StorageAdviser::UseMemory) {
-        
-        // can't use disc, must use memory
-
+    if ((recommendation & StorageAdviser::UseMemory) ||
+        (recommendation & StorageAdviser::PreferMemory)) {
         m_memoryCache = true;
-
-    } else if (recommendation & StorageAdviser::PreferMemory) {
-
-        // if memory is recommended, we use it if we're using polar
-        // coordinates; but we don't have a native rectangular memory
-        // cache, so we might as well use disc if we want rectangular
-        // coordinates rather than have all the bother of converting
-        // every time
-
-        if (m_polar) m_memoryCache = true;
     }
 
-    m_compactCache = (recommendation & StorageAdviser::ConserveSpace);
+    m_compactCache = canCompact &&
+        (recommendation & StorageAdviser::ConserveSpace);
+
+    std::cerr << "FFTDataServer: memory cache = " << m_memoryCache << ", compact cache = " << m_compactCache << std::endl;
     
 #ifdef DEBUG_FFT_SERVER
     std::cerr << "Width " << m_width << ", cache width " << m_cacheWidth << " (size " << m_cacheWidth * columnSize << ")" << std::endl;
@@ -616,9 +618,9 @@
         fftf_malloc((fftSize+2) * sizeof(float));
 
     m_fftPlan = fftf_plan_dft_r2c_1d(m_fftSize,
-                                      m_fftInput,
-                                      m_fftOutput,
-                                      FFTW_MEASURE);
+                                     m_fftInput,
+                                     m_fftOutput,
+                                     FFTW_MEASURE);
 
     if (!m_fftPlan) {
         std::cerr << "ERROR: fftf_plan_dft_r2c_1d(" << m_windowSize << ") failed!" << std::endl;
@@ -788,7 +790,9 @@
 
             cache = new FFTMemoryCache
                 (m_compactCache ? FFTMemoryCache::Compact :
-                                  FFTMemoryCache::Polar);
+//                                  FFTMemoryCache::Polar);
+                 m_polar ? FFTMemoryCache::Polar :
+                           FFTMemoryCache::Rectangular);
 
         } else if (m_compactCache) {
 
--- a/data/fft/FFTDataServer.h	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fft/FFTDataServer.h	Sun Nov 11 20:31:12 2007 +0000
@@ -18,6 +18,7 @@
 
 #include "base/Window.h"
 #include "base/Thread.h"
+#include "base/StorageAdviser.h"
 
 #include "FFTapi.h"
 
@@ -42,6 +43,8 @@
                                       size_t windowIncrement,
                                       size_t fftSize,
                                       bool polar,
+                                      StorageAdviser::Criteria criteria =
+                                          StorageAdviser::NoCriteria,
                                       size_t fillFromColumn = 0);
 
     static FFTDataServer *getFuzzyInstance(const DenseTimeValueModel *model,
@@ -51,6 +54,8 @@
                                            size_t windowIncrement,
                                            size_t fftSize,
                                            bool polar,
+                                           StorageAdviser::Criteria criteria =
+                                               StorageAdviser::NoCriteria,
                                            size_t fillFromColumn = 0);
 
     static void claimInstance(FFTDataServer *);
@@ -104,6 +109,7 @@
                   size_t windowIncrement,
                   size_t fftSize,
                   bool polar,
+                  StorageAdviser::Criteria criteria,
                   size_t fillFromColumn = 0);
 
     virtual ~FFTDataServer();
--- a/data/fft/FFTMemoryCache.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fft/FFTMemoryCache.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -25,6 +25,8 @@
     m_phase(0),
     m_fmagnitude(0),
     m_fphase(0),
+    m_freal(0),
+    m_fimag(0),
     m_factor(0),
     m_storageType(storageType)
 {
@@ -41,12 +43,16 @@
 	if (m_phase && m_phase[i]) free(m_phase[i]);
 	if (m_fmagnitude && m_fmagnitude[i]) free(m_fmagnitude[i]);
 	if (m_fphase && m_fphase[i]) free(m_fphase[i]);
+        if (m_freal && m_freal[i]) free(m_freal[i]);
+        if (m_fimag && m_fimag[i]) free(m_fimag[i]);
     }
 
     if (m_magnitude) free(m_magnitude);
     if (m_phase) free(m_phase);
     if (m_fmagnitude) free(m_fmagnitude);
     if (m_fphase) free(m_fphase);
+    if (m_freal) free(m_freal);
+    if (m_fimag) free(m_fimag);
     if (m_factor) free(m_factor);
 }
 
@@ -60,9 +66,12 @@
     if (m_storageType == Compact) {
         resize(m_magnitude, width, height);
         resize(m_phase, width, height);
-    } else {
+    } else if (m_storageType == Polar) {
         resize(m_fmagnitude, width, height);
         resize(m_fphase, width, height);
+    } else {
+        resize(m_freal, width, height);
+        resize(m_fimag, width, height);
     }
 
     m_colset.resize(width);
@@ -147,16 +156,55 @@
             m_factor[x] = 1.0;
         }
         break;
+
+    case Rectangular:
+        for (size_t x = 0; x < m_width; ++x) {
+            for (size_t y = 0; y < m_height; ++y) {
+                m_freal[x][y] = 0;
+                m_fimag[x][y] = 0;
+            }
+            m_factor[x] = 1.0;
+        }
+        break;        
     }
 }	    
 
 void
+FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
+{
+    setNormalizationFactor(x, factor);
+
+    if (m_storageType == Rectangular) {
+        for (size_t y = 0; y < m_height; ++y) {
+            m_freal[x][y] = mags[y] * cosf(phases[y]);
+            m_fimag[x][y] = mags[y] * sinf(phases[y]);
+        }
+    } else {
+        for (size_t y = 0; y < m_height; ++y) {
+            setMagnitudeAt(x, y, mags[y]);
+            setPhaseAt(x, y, phases[y]);
+        }
+    }
+
+    m_colset.set(x);
+}
+
+void
 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags)
 {
     float max = 0.0;
 
     switch (m_storageType) {
 
+    case Rectangular:
+        for (size_t y = 0; y < m_height; ++y) {
+            m_freal[x][y] = reals[y];
+            m_fimag[x][y] = imags[y];
+            float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]);
+            if (mag > max) max = mag;
+        }
+        break;
+
     case Compact:
     case Polar:
         for (size_t y = 0; y < m_height; ++y) {
@@ -170,7 +218,12 @@
         break;
     };
 
-    setColumnAt(x, reals, imags, max);
+    if (m_storageType == Rectangular) {
+        m_factor[x] = max;
+        m_colset.set(x);
+    } else {
+        setColumnAt(x, reals, imags, max);
+    }
 }
 
 size_t
@@ -184,6 +237,7 @@
         sz = (height * 2 + 1) * width * sizeof(uint16_t);
 
     case Polar:
+    case Rectangular:
         sz = (height * 2 + 1) * width * sizeof(float);
     }
 
--- a/data/fft/FFTMemoryCache.h	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fft/FFTMemoryCache.h	Sun Nov 11 20:31:12 2007 +0000
@@ -44,7 +44,8 @@
 public:
     enum StorageType {
         Compact, // 16 bits normalized polar
-        Polar, // floating point mag+phase
+        Rectangular, // floating point real+imag
+        Polar // floating point mag+phase
     };
 
     FFTMemoryCache(StorageType storageType); // of size zero, call resize() before using
@@ -57,11 +58,17 @@
     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];
+        if (m_storageType == Rectangular) {
+            return sqrt(m_freal[x][y] * m_freal[x][y] +
+                        m_fimag[x][y] * m_fimag[x][y]);
+        } else {
+            return getNormalizedMagnitudeAt(x, y) * m_factor[x];
+        }
     }
     
     virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
-        if (m_storageType == Polar) return m_fmagnitude[x][y];
+        if (m_storageType == Rectangular) return getMagnitudeAt(x, y) / m_factor[x];
+        else if (m_storageType == Polar) return m_fmagnitude[x][y];
         else return float(m_magnitude[x][y]) / 65535.0;
     }
     
@@ -70,18 +77,51 @@
     }
     
     virtual float getPhaseAt(size_t x, size_t y) const {
-        if (m_storageType == Polar) return m_fphase[x][y];
-        int16_t i = (int16_t)m_phase[x][y];
-        return (float(i) / 32767.0) * M_PI;
+        if (m_storageType == Rectangular) {
+            return atan2f(m_fimag[x][y], m_freal[x][y]);
+        } else if (m_storageType == Polar) {
+            return m_fphase[x][y];
+        } else {
+            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);
+        if (m_storageType == Rectangular) {
+            real = m_freal[x][y];
+            imag = m_fimag[x][y];
+        } else {
+            float mag = getMagnitudeAt(x, y);
+            float phase = getPhaseAt(x, y);
+            real = mag * cosf(phase);
+            imag = mag * sinf(phase);
+        }
     }
 
+    virtual bool haveSetColumnAt(size_t x) const {
+        return m_colset.get(x);
+    }
+
+    virtual void setColumnAt(size_t x, float *mags, float *phases, float factor);
+
+    virtual void setColumnAt(size_t x, float *reals, float *imags);
+
+    static size_t getCacheSize(size_t width, size_t height, StorageType type);
+
+private:
+    size_t m_width;
+    size_t m_height;
+    uint16_t **m_magnitude;
+    uint16_t **m_phase;
+    float **m_fmagnitude;
+    float **m_fphase;
+    float **m_freal;
+    float **m_fimag;
+    float *m_factor;
+    StorageType m_storageType;
+    ResizeableBitset m_colset;
+
     virtual void setNormalizationFactor(size_t x, float factor) {
         if (x < m_width) m_factor[x] = factor;
     }
@@ -105,34 +145,6 @@
             else 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);
-
-    static size_t getCacheSize(size_t width, size_t height, StorageType type);
-
-private:
-    size_t m_width;
-    size_t m_height;
-    uint16_t **m_magnitude;
-    uint16_t **m_phase;
-    float **m_fmagnitude;
-    float **m_fphase;
-    float *m_factor;
-    StorageType m_storageType;
-    ResizeableBitset m_colset;
 
     void resize(uint16_t **&, size_t, size_t);
     void resize(float **&, size_t, size_t);
--- a/data/fileio/MP3FileReader.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fileio/MP3FileReader.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -227,6 +227,13 @@
         
     QString rv = QString::fromUtf8((const char *)u8str);
     free(u8str);
+
+#ifdef DEBUG_ID3TAG
+	std::cerr << "MP3FileReader::loadTags: tag \"" << name << "\" -> \""
+	<< rv.toStdString() << "\"" << std::endl;
+#endif
+
+
     return rv;
 
 #else
--- a/data/fileio/MP3FileReader.h	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/fileio/MP3FileReader.h	Sun Nov 11 20:31:12 2007 +0000
@@ -44,6 +44,7 @@
     virtual QString getError() const { return m_error; }
 
     virtual QString getTitle() const { return m_title; }
+    virtual QString getMaker() const { return m_maker; }
     
     static void getSupportedExtensions(std::set<QString> &extensions);
     static bool supportsExtension(QString ext);
--- a/data/model/FFTModel.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/model/FFTModel.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -29,6 +29,7 @@
                    size_t windowIncrement,
                    size_t fftSize,
                    bool polar,
+                   StorageAdviser::Criteria criteria,
                    size_t fillFromColumn) :
     //!!! ZoomConstraint!
     m_server(0),
@@ -44,6 +45,7 @@
                          windowIncrement,
                          fftSize,
                          polar,
+                         criteria,
                          fillFromColumn);
 
     if (!m_server) return; // caller should check isOK()
@@ -88,6 +90,7 @@
                     size_t windowIncrement,
                     size_t fftSize,
                     bool polar,
+                    StorageAdviser::Criteria criteria,
                     size_t fillFromColumn)
 {
     // Obviously, an FFT model of channel C (where C != -1) of an
@@ -119,6 +122,7 @@
                              windowIncrement,
                              fftSize,
                              polar,
+                             criteria,
                              fillFromColumn);
         }
     }
@@ -132,6 +136,7 @@
                                            windowIncrement,
                                            fftSize,
                                            polar,
+                                           criteria,
                                            fillFromColumn);
 }
 
--- a/data/model/FFTModel.h	Fri Nov 09 17:46:58 2007 +0000
+++ b/data/model/FFTModel.h	Sun Nov 11 20:31:12 2007 +0000
@@ -60,6 +60,7 @@
              size_t windowIncrement,
              size_t fftSize,
              bool polar,
+             StorageAdviser::Criteria criteria = StorageAdviser::NoCriteria,
              size_t fillFromColumn = 0);
     ~FFTModel();
 
@@ -174,7 +175,7 @@
 
     FFTDataServer *getServer(const DenseTimeValueModel *,
                              int, WindowType, size_t, size_t, size_t,
-                             bool, size_t);
+                             bool, StorageAdviser::Criteria, size_t);
 
     size_t getPeakPickWindowSize(PeakPickType type, size_t sampleRate,
                                  size_t bin, float &percentile) const;
--- a/plugin/transform/FeatureExtractionModelTransformer.cpp	Fri Nov 09 17:46:58 2007 +0000
+++ b/plugin/transform/FeatureExtractionModelTransformer.cpp	Sun Nov 11 20:31:12 2007 +0000
@@ -283,7 +283,8 @@
                                    m_context.blockSize,
                                    m_context.stepSize,
                                    m_context.blockSize,
-                                   false);
+                                   false,
+                                   StorageAdviser::PrecisionCritical);
             if (!model->isOK()) {
                 QMessageBox::critical
                     (0, tr("FFT cache failed"),