# HG changeset patch # User Chris Cannam # Date 1194813072 0 # Node ID aa8dbac62024479b4dd326103d6943905026affc # Parent 1afaf98dbf1122aab250c88f28585ce0829ad482 * Pass StorageAdviser::Criteria into FFTModel constructor etc diff -r 1afaf98dbf11 -r aa8dbac62024 base/StorageAdviser.cpp --- 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 diff -r 1afaf98dbf11 -r aa8dbac62024 base/StorageAdviser.h --- 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: */ /* diff -r 1afaf98dbf11 -r aa8dbac62024 data/fft/FFTDataServer.cpp --- 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) { diff -r 1afaf98dbf11 -r aa8dbac62024 data/fft/FFTDataServer.h --- 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(); diff -r 1afaf98dbf11 -r aa8dbac62024 data/fft/FFTMemoryCache.cpp --- 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); } diff -r 1afaf98dbf11 -r aa8dbac62024 data/fft/FFTMemoryCache.h --- 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); diff -r 1afaf98dbf11 -r aa8dbac62024 data/fileio/MP3FileReader.cpp --- 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 diff -r 1afaf98dbf11 -r aa8dbac62024 data/fileio/MP3FileReader.h --- 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 &extensions); static bool supportsExtension(QString ext); diff -r 1afaf98dbf11 -r aa8dbac62024 data/model/FFTModel.cpp --- 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); } diff -r 1afaf98dbf11 -r aa8dbac62024 data/model/FFTModel.h --- 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; diff -r 1afaf98dbf11 -r aa8dbac62024 plugin/transform/FeatureExtractionModelTransformer.cpp --- 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"),