Mercurial > hg > svcore
changeset 152:21792a550ec9 last-cc-copyright
* Move the current DenseThreeDimensionalModel to EditableDenseThreeDimensionalModel
(wow!), and make DTDM an abstract base
* Move FFTFuzzyAdapter to FFTModel as a new subclass of DTDM
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 17:05:18 +0000 |
parents | 3c1d5ef43baa |
children | 8d92611901d3 |
files | base/FFTCache.cpp base/FFTCache.h base/base.pro data/data.pro data/fft/FFTCache.cpp data/fft/FFTCache.h data/fft/FFTDataServer.cpp data/fft/FFTDataServer.h data/fft/FFTFileCache.h data/fft/FFTFuzzyAdapter.cpp data/fft/FFTFuzzyAdapter.h data/fileio/CSVFileReader.cpp data/model/DenseThreeDimensionalModel.cpp data/model/DenseThreeDimensionalModel.h data/model/EditableDenseThreeDimensionalModel.cpp data/model/EditableDenseThreeDimensionalModel.h data/model/FFTModel.cpp data/model/FFTModel.h |
diffstat | 18 files changed, 1006 insertions(+), 830 deletions(-) [+] |
line wrap: on
line diff
--- a/base/FFTCache.cpp Mon Jul 31 16:15:45 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/base/FFTCache.h Mon Jul 31 16:15:45 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +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. -*/ - -#ifndef _FFT_CACHE_H_ -#define _FFT_CACHE_H_ - -#include <cstdlib> -#include <cmath> - -#include <stdint.h> - -class FFTCache -{ -public: - virtual ~FFTCache() { } - - virtual size_t getWidth() const = 0; - virtual size_t getHeight() const = 0; - - virtual void resize(size_t width, size_t height) = 0; - virtual void reset() = 0; // zero-fill or 1-fill as appropriate without changing size - - virtual float getMagnitudeAt(size_t x, size_t y) const = 0; - virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const = 0; - virtual float getMaximumMagnitudeAt(size_t x) const = 0; - virtual float getPhaseAt(size_t x, size_t y) const = 0; - - virtual void getValuesAt(size_t x, size_t y, float &real, float &imaginary) const = 0; - - virtual bool haveSetColumnAt(size_t x) const = 0; - - // may modify argument arrays - virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) = 0; - - // may modify argument arrays - virtual void setColumnAt(size_t x, float *reals, float *imags) = 0; - - virtual void suspend() { } - -protected: - FFTCache() { } -}; - - -/** - * 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/base/base.pro Mon Jul 31 16:15:45 2006 +0000 +++ b/base/base.pro Mon Jul 31 17:05:18 2006 +0000 @@ -20,7 +20,6 @@ CommandHistory.h \ ConfigFile.h \ Exceptions.h \ - FFTCache.h \ Pitch.h \ PlayParameterRepository.h \ PlayParameters.h \ @@ -45,7 +44,6 @@ CommandHistory.cpp \ ConfigFile.cpp \ Exceptions.cpp \ - FFTCache.cpp \ Pitch.cpp \ PlayParameterRepository.cpp \ PlayParameters.cpp \
--- a/data/data.pro Mon Jul 31 16:15:45 2006 +0000 +++ b/data/data.pro Mon Jul 31 17:05:18 2006 +0000 @@ -13,9 +13,9 @@ MOC_DIR = tmp_moc # Input -HEADERS += fft/FFTDataServer.h \ +HEADERS += fft/FFTCache.h \ + fft/FFTDataServer.h \ fft/FFTFileCache.h \ - fft/FFTFuzzyAdapter.h \ fileio/AudioFileReader.h \ fileio/AudioFileReaderFactory.h \ fileio/BZipFileDevice.h \ @@ -33,6 +33,8 @@ fileio/WavFileWriter.h \ model/DenseThreeDimensionalModel.h \ model/DenseTimeValueModel.h \ + model/EditableDenseThreeDimensionalModel.h \ + model/FFTModel.h \ model/Model.h \ model/NoteModel.h \ model/PowerOfSqrtTwoZoomConstraint.h \ @@ -44,9 +46,9 @@ model/SparseValueModel.h \ model/TextModel.h \ model/WaveFileModel.h -SOURCES += fft/FFTDataServer.cpp \ +SOURCES += fft/FFTCache.cpp \ + fft/FFTDataServer.cpp \ fft/FFTFileCache.cpp \ - fft/FFTFuzzyAdapter.cpp \ fileio/AudioFileReaderFactory.cpp \ fileio/BZipFileDevice.cpp \ fileio/CodedAudioFileReader.cpp \ @@ -60,8 +62,9 @@ fileio/OggVorbisFileReader.cpp \ fileio/WavFileReader.cpp \ fileio/WavFileWriter.cpp \ - model/DenseThreeDimensionalModel.cpp \ model/DenseTimeValueModel.cpp \ + model/EditableDenseThreeDimensionalModel.cpp \ + model/FFTModel.cpp \ model/Model.cpp \ model/NoteModel.cpp \ model/PowerOfSqrtTwoZoomConstraint.cpp \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fft/FFTCache.cpp Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,118 @@ +/* -*- 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); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fft/FFTCache.h Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,158 @@ +/* -*- 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_CACHE_H_ +#define _FFT_CACHE_H_ + +#include <cstdlib> +#include <cmath> + +#include <stdint.h> + +class FFTCache +{ +public: + virtual ~FFTCache() { } + + virtual size_t getWidth() const = 0; + virtual size_t getHeight() const = 0; + + virtual void resize(size_t width, size_t height) = 0; + virtual void reset() = 0; // zero-fill or 1-fill as appropriate without changing size + + virtual float getMagnitudeAt(size_t x, size_t y) const = 0; + virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const = 0; + virtual float getMaximumMagnitudeAt(size_t x) const = 0; + virtual float getPhaseAt(size_t x, size_t y) const = 0; + + virtual void getValuesAt(size_t x, size_t y, float &real, float &imaginary) const = 0; + + virtual bool haveSetColumnAt(size_t x) const = 0; + + // may modify argument arrays + virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) = 0; + + // may modify argument arrays + virtual void setColumnAt(size_t x, float *reals, float *imags) = 0; + + virtual void suspend() { } + +protected: + FFTCache() { } +}; + + +/** + * 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 Mon Jul 31 16:15:45 2006 +0000 +++ b/data/fft/FFTDataServer.cpp Mon Jul 31 17:05:18 2006 +0000 @@ -112,11 +112,11 @@ // smaller increment, we can draw the results from it (provided // our increment is a multiple of its) // - // The FFTFuzzyAdapter knows how to interpret these things. In + // The FFTModel knows how to interpret these things. In // both cases we require that the larger one is a power-of-two // multiple of the smaller (e.g. even though in principle you can // draw the results at increment 256 from those at increment 768 - // or 1536, the fuzzy adapter doesn't support this). + // or 1536, the model doesn't support this). { QMutexLocker locker(&m_serverMapMutex); @@ -208,6 +208,23 @@ } void +FFTDataServer::claimInstance(FFTDataServer *server) +{ + + QMutexLocker locker(&m_serverMapMutex); + + for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { + if (i->second.first == server) { + ++i->second.second; + return; + } + } + + std::cerr << "ERROR: FFTDataServer::claimInstance: instance " + << server << " unknown!" << std::endl; +} + +void FFTDataServer::releaseInstance(FFTDataServer *server) { #ifdef DEBUG_FFT_SERVER
--- a/data/fft/FFTDataServer.h Mon Jul 31 16:15:45 2006 +0000 +++ b/data/fft/FFTDataServer.h Mon Jul 31 17:05:18 2006 +0000 @@ -52,6 +52,7 @@ bool polar, size_t fillFromColumn = 0); + static void claimInstance(FFTDataServer *); static void releaseInstance(FFTDataServer *); const DenseTimeValueModel *getModel() const { return m_model; }
--- a/data/fft/FFTFileCache.h Mon Jul 31 16:15:45 2006 +0000 +++ b/data/fft/FFTFileCache.h Mon Jul 31 17:05:18 2006 +0000 @@ -16,7 +16,7 @@ #ifndef _FFT_FILE_CACHE_H_ #define _FFT_FILE_CACHE_H_ -#include "base/FFTCache.h" +#include "FFTCache.h" #include "fileio/MatrixFile.h" #include <QMutex>
--- a/data/fft/FFTFuzzyAdapter.cpp Mon Jul 31 16:15:45 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +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 "FFTFuzzyAdapter.h" - -#include <cassert> - -FFTFuzzyAdapter::FFTFuzzyAdapter(const DenseTimeValueModel *model, - int channel, - WindowType windowType, - size_t windowSize, - size_t windowIncrement, - size_t fftSize, - bool polar, - size_t fillFromColumn) : - m_server(0), - m_xshift(0), - m_yshift(0) -{ - m_server = FFTDataServer::getFuzzyInstance(model, - channel, - windowType, - windowSize, - windowIncrement, - fftSize, - polar, - fillFromColumn); - - size_t xratio = windowIncrement / m_server->getWindowIncrement(); - size_t yratio = m_server->getFFTSize() / fftSize; - - while (xratio > 1) { - if (xratio & 0x1) { - std::cerr << "ERROR: FFTFuzzyAdapter: Window increment ratio " - << windowIncrement << " / " - << m_server->getWindowIncrement() - << " must be a power of two" << std::endl; - assert(!(xratio & 0x1)); - } - ++m_xshift; - xratio >>= 1; - } - - while (yratio > 1) { - if (yratio & 0x1) { - std::cerr << "ERROR: FFTFuzzyAdapter: FFT size ratio " - << m_server->getFFTSize() << " / " << fftSize - << " must be a power of two" << std::endl; - assert(!(yratio & 0x1)); - } - ++m_yshift; - yratio >>= 1; - } -} - -FFTFuzzyAdapter::~FFTFuzzyAdapter() -{ - FFTDataServer::releaseInstance(m_server); -} -
--- a/data/fft/FFTFuzzyAdapter.h Mon Jul 31 16:15:45 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +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. -*/ - -#ifndef _FFT_FUZZY_ADAPTER_H_ -#define _FFT_FUZZY_ADAPTER_H_ - -#include "FFTDataServer.h" - -class FFTFuzzyAdapter -{ -public: - FFTFuzzyAdapter(const DenseTimeValueModel *model, - int channel, - WindowType windowType, - size_t windowSize, - size_t windowIncrement, - size_t fftSize, - bool polar, - size_t fillFromColumn = 0); - ~FFTFuzzyAdapter(); - - size_t getWidth() const { - return m_server->getWidth() >> m_xshift; - } - size_t getHeight() const { - return m_server->getHeight() >> m_yshift; - } - float getMagnitudeAt(size_t x, size_t y) { - return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift); - } - float getNormalizedMagnitudeAt(size_t x, size_t y) { - return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift); - } - float getMaximumMagnitudeAt(size_t x) { - return m_server->getMaximumMagnitudeAt(x << m_xshift); - } - float getPhaseAt(size_t x, size_t y) { - return m_server->getPhaseAt(x << m_xshift, y << m_yshift); - } - void getValuesAt(size_t x, size_t y, float &real, float &imaginary) { - m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary); - } - bool isColumnReady(size_t x) { - return m_server->isColumnReady(x << m_xshift); - } - bool isLocalPeak(size_t x, size_t y) { - float mag = getMagnitudeAt(x, y); - if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false; - if (y < getHeight() - 1 && mag < getMagnitudeAt(x, y + 1)) return false; - return true; - } - bool isOverThreshold(size_t x, size_t y, float threshold) { - return getMagnitudeAt(x, y) > threshold; - } - - size_t getFillCompletion() const { return m_server->getFillCompletion(); } - size_t getFillExtent() const { return m_server->getFillExtent(); } - -private: - FFTFuzzyAdapter(const FFTFuzzyAdapter &); // not implemented - FFTFuzzyAdapter &operator=(const FFTFuzzyAdapter &); // not implemented - - FFTDataServer *m_server; - int m_xshift; - int m_yshift; -}; - -#endif
--- a/data/fileio/CSVFileReader.cpp Mon Jul 31 16:15:45 2006 +0000 +++ b/data/fileio/CSVFileReader.cpp Mon Jul 31 17:05:18 2006 +0000 @@ -19,7 +19,7 @@ #include "base/RealTime.h" #include "model/SparseOneDimensionalModel.h" #include "model/SparseTimeValueModel.h" -#include "model/DenseThreeDimensionalModel.h" +#include "model/EditableDenseThreeDimensionalModel.h" #include <QFile> #include <QString> @@ -112,7 +112,7 @@ SparseOneDimensionalModel *model1 = 0; SparseTimeValueModel *model2 = 0; - DenseThreeDimensionalModel *model3 = 0; + EditableDenseThreeDimensionalModel *model3 = 0; Model *model = 0; QTextStream in(m_file); @@ -149,8 +149,9 @@ break; case CSVFormatDialog::ThreeDimensionalModel: - model3 = new DenseThreeDimensionalModel(sampleRate, windowSize, - list.size()); + model3 = new EditableDenseThreeDimensionalModel(sampleRate, + windowSize, + list.size()); model = model3; break; }
--- a/data/model/DenseThreeDimensionalModel.cpp Mon Jul 31 16:15:45 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,314 +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 "DenseThreeDimensionalModel.h" - -#include <QTextStream> - -DenseThreeDimensionalModel::DenseThreeDimensionalModel(size_t sampleRate, - size_t windowSize, - size_t yBinCount, - bool notifyOnAdd) : - m_sampleRate(sampleRate), - m_windowSize(windowSize), - m_yBinCount(yBinCount), - m_minimum(0.0), - m_maximum(0.0), - m_notifyOnAdd(notifyOnAdd), - m_sinceLastNotifyMin(-1), - m_sinceLastNotifyMax(-1), - m_completion(100) -{ -} - -bool -DenseThreeDimensionalModel::isOK() const -{ - return true; -} - -size_t -DenseThreeDimensionalModel::getSampleRate() const -{ - return m_sampleRate; -} - -size_t -DenseThreeDimensionalModel::getStartFrame() const -{ - return 0; -} - -size_t -DenseThreeDimensionalModel::getEndFrame() const -{ - return m_windowSize * m_data.size() + (m_windowSize - 1); -} - -Model * -DenseThreeDimensionalModel::clone() const -{ - DenseThreeDimensionalModel *model = new DenseThreeDimensionalModel - (m_sampleRate, m_windowSize, m_yBinCount); - - model->m_minimum = m_minimum; - model->m_maximum = m_maximum; - - for (size_t i = 0; i < m_data.size(); ++i) { - model->setBinValues(i * m_windowSize, m_data[i]); - } - - return model; -} - -size_t -DenseThreeDimensionalModel::getWindowSize() const -{ - return m_windowSize; -} - -void -DenseThreeDimensionalModel::setWindowSize(size_t sz) -{ - m_windowSize = sz; -} - -size_t -DenseThreeDimensionalModel::getYBinCount() const -{ - return m_yBinCount; -} - -void -DenseThreeDimensionalModel::setYBinCount(size_t sz) -{ - m_yBinCount = sz; -} - -float -DenseThreeDimensionalModel::getMinimumLevel() const -{ - return m_minimum; -} - -void -DenseThreeDimensionalModel::setMinimumLevel(float level) -{ - m_minimum = level; -} - -float -DenseThreeDimensionalModel::getMaximumLevel() const -{ - return m_maximum; -} - -void -DenseThreeDimensionalModel::setMaximumLevel(float level) -{ - m_maximum = level; -} - -void -DenseThreeDimensionalModel::getBinValues(long windowStart, - BinValueSet &result) const -{ - QMutexLocker locker(&m_mutex); - - long index = windowStart / m_windowSize; - - if (index >= 0 && index < long(m_data.size())) { - result = m_data[index]; - } else { - result.clear(); - } - - while (result.size() < m_yBinCount) result.push_back(m_minimum); -} - -float -DenseThreeDimensionalModel::getBinValue(long windowStart, - size_t n) const -{ - QMutexLocker locker(&m_mutex); - - long index = windowStart / m_windowSize; - - if (index >= 0 && index < long(m_data.size())) { - const BinValueSet &s = m_data[index]; - if (n < s.size()) return s[n]; - } - - return m_minimum; -} - -void -DenseThreeDimensionalModel::setBinValues(long windowStart, - const BinValueSet &values) -{ - QMutexLocker locker(&m_mutex); - - long index = windowStart / m_windowSize; - - while (index >= long(m_data.size())) { - m_data.push_back(BinValueSet()); - } - - bool newExtents = (m_data.empty() && (m_minimum == m_maximum)); - bool allChange = false; - - for (size_t i = 0; i < values.size(); ++i) { - if (newExtents || values[i] < m_minimum) { - m_minimum = values[i]; - allChange = true; - } - if (newExtents || values[i] > m_maximum) { - m_maximum = values[i]; - allChange = true; - } - } - - m_data[index] = values; - - if (m_notifyOnAdd) { - if (allChange) { - emit modelChanged(); - } else { - emit modelChanged(windowStart, windowStart + m_windowSize); - } - } else { - if (allChange) { - m_sinceLastNotifyMin = -1; - m_sinceLastNotifyMax = -1; - emit modelChanged(); - } else { - if (m_sinceLastNotifyMin == -1 || - windowStart < m_sinceLastNotifyMin) { - m_sinceLastNotifyMin = windowStart; - } - if (m_sinceLastNotifyMax == -1 || - windowStart > m_sinceLastNotifyMax) { - m_sinceLastNotifyMax = windowStart; - } - } - } -} - -QString -DenseThreeDimensionalModel::getBinName(size_t n) const -{ - if (m_binNames.size() > n) return m_binNames[n]; - else return ""; -} - -void -DenseThreeDimensionalModel::setBinName(size_t n, QString name) -{ - while (m_binNames.size() <= n) m_binNames.push_back(""); - m_binNames[n] = name; - emit modelChanged(); -} - -void -DenseThreeDimensionalModel::setBinNames(std::vector<QString> names) -{ - m_binNames = names; - emit modelChanged(); -} - -void -DenseThreeDimensionalModel::setCompletion(int completion) -{ - if (m_completion != completion) { - m_completion = completion; - - if (completion == 100) { - - m_notifyOnAdd = true; // henceforth - emit modelChanged(); - - } else if (!m_notifyOnAdd) { - - if (m_sinceLastNotifyMin >= 0 && - m_sinceLastNotifyMax >= 0) { - emit modelChanged(m_sinceLastNotifyMin, - m_sinceLastNotifyMax + m_windowSize); - m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; - } else { - emit completionChanged(); - } - } else { - emit completionChanged(); - } - } -} - -void -DenseThreeDimensionalModel::toXml(QTextStream &out, - QString indent, - QString extraAttributes) const -{ - out << Model::toXmlString - (indent, QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6") - .arg(m_windowSize) - .arg(m_yBinCount) - .arg(m_minimum) - .arg(m_maximum) - .arg(getObjectExportId(&m_data)) - .arg(extraAttributes)); - - out << indent; - out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n") - .arg(getObjectExportId(&m_data)); - - for (size_t i = 0; i < m_binNames.size(); ++i) { - if (m_binNames[i] != "") { - out << indent + " "; - out << QString("<bin number=\"%1\" name=\"%2\"/>\n") - .arg(i).arg(m_binNames[i]); - } - } - - for (size_t i = 0; i < m_data.size(); ++i) { - out << indent + " "; - out << QString("<row n=\"%1\">").arg(i); - for (size_t j = 0; j < m_data[i].size(); ++j) { - if (j > 0) out << " "; - out << m_data[i][j]; - } - out << QString("</row>\n"); - } - - out << indent + "</dataset>\n"; -} - -QString -DenseThreeDimensionalModel::toXmlString(QString indent, - QString extraAttributes) const -{ - QString s; - - { - QTextStream out(&s); - toXml(out, indent, extraAttributes); - } - - return s; -} - -#ifdef INCLUDE_MOCFILES -#include "DenseThreeDimensionalModel.moc.cpp" -#endif -
--- a/data/model/DenseThreeDimensionalModel.h Mon Jul 31 16:15:45 2006 +0000 +++ b/data/model/DenseThreeDimensionalModel.h Mon Jul 31 17:05:18 2006 +0000 @@ -29,60 +29,25 @@ Q_OBJECT public: - //!!! need to reconcile terminology -- windowSize here, resolution in sparse models - DenseThreeDimensionalModel(size_t sampleRate, - size_t windowSize, - size_t yBinCount, - bool notifyOnAdd = true); - - virtual bool isOK() const; - - virtual size_t getSampleRate() const; - virtual size_t getStartFrame() const; - virtual size_t getEndFrame() const; - - virtual Model *clone() const; - - /** * Return the number of sample frames covered by each set of bins. */ - virtual size_t getWindowSize() const; - - /** - * Set the number of sample frames covered by each set of bins. - */ - virtual void setWindowSize(size_t sz); + virtual size_t getResolution() const = 0; /** * Return the number of bins in each set of bins. */ - virtual size_t getYBinCount() const; - - /** - * Set the number of bins in each set of bins. - */ - virtual void setYBinCount(size_t sz); + virtual size_t getYBinCount() const = 0; /** * Return the minimum value of the value in each bin. */ - virtual float getMinimumLevel() const; - - /** - * Set the minimum value of the value in a bin. - */ - virtual void setMinimumLevel(float sz); + virtual float getMinimumLevel() const = 0; /** * Return the maximum value of the value in each bin. */ - virtual float getMaximumLevel() const; - - /** - * Set the maximum value of the value in a bin. - */ - virtual void setMaximumLevel(float sz); + virtual float getMaximumLevel() const = 0; typedef std::vector<float> BinValueSet; @@ -90,50 +55,20 @@ * Get the set of bin values at the given sample frame (i.e. the * windowStartFrame/getWindowSize()'th set of bins). */ - virtual void getBinValues(long windowStartFrame, BinValueSet &result) const; + virtual void getBinValues(long windowStartFrame, BinValueSet &result) const = 0; /** * Get a single value, the one at the n'th bin of the set of bins * starting at the given sample frame. */ - virtual float getBinValue(long windowStartFrame, size_t n) const; + virtual float getBinValue(long windowStartFrame, size_t n) const = 0; - /** - * Set the entire set of bin values at the given sample frame. - */ - virtual void setBinValues(long windowStartFrame, const BinValueSet &values); + virtual QString getBinName(size_t n) const = 0; - virtual QString getBinName(size_t n) const; - virtual void setBinName(size_t n, QString); - virtual void setBinNames(std::vector<QString> names); - - virtual void setCompletion(int completion); - virtual int getCompletion() const { return m_completion; } - - virtual void toXml(QTextStream &out, - QString indent = "", - QString extraAttributes = "") const; - - virtual QString toXmlString(QString indent = "", - QString extraAttributes = "") const; + virtual int getCompletion() const = 0; protected: - typedef std::vector<BinValueSet> ValueMatrix; - ValueMatrix m_data; - - std::vector<QString> m_binNames; - - size_t m_sampleRate; - size_t m_windowSize; - size_t m_yBinCount; - float m_minimum; - float m_maximum; - bool m_notifyOnAdd; - long m_sinceLastNotifyMin; - long m_sinceLastNotifyMax; - int m_completion; - - mutable QMutex m_mutex; + DenseThreeDimensionalModel() { } }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/EditableDenseThreeDimensionalModel.cpp Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,317 @@ +/* -*- 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 "EditableDenseThreeDimensionalModel.h" + +#include <QTextStream> + +EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate, + size_t resolution, + size_t yBinCount, + bool notifyOnAdd) : + m_sampleRate(sampleRate), + m_resolution(resolution), + m_yBinCount(yBinCount), + m_minimum(0.0), + m_maximum(0.0), + m_notifyOnAdd(notifyOnAdd), + m_sinceLastNotifyMin(-1), + m_sinceLastNotifyMax(-1), + m_completion(100) +{ +} + +bool +EditableDenseThreeDimensionalModel::isOK() const +{ + return true; +} + +size_t +EditableDenseThreeDimensionalModel::getSampleRate() const +{ + return m_sampleRate; +} + +size_t +EditableDenseThreeDimensionalModel::getStartFrame() const +{ + return 0; +} + +size_t +EditableDenseThreeDimensionalModel::getEndFrame() const +{ + return m_resolution * m_data.size() + (m_resolution - 1); +} + +Model * +EditableDenseThreeDimensionalModel::clone() const +{ + EditableDenseThreeDimensionalModel *model = + new EditableDenseThreeDimensionalModel + (m_sampleRate, m_resolution, m_yBinCount); + + model->m_minimum = m_minimum; + model->m_maximum = m_maximum; + + for (size_t i = 0; i < m_data.size(); ++i) { + model->setBinValues(i * m_resolution, m_data[i]); + } + + return model; +} + +size_t +EditableDenseThreeDimensionalModel::getResolution() const +{ + return m_resolution; +} + +void +EditableDenseThreeDimensionalModel::setResolution(size_t sz) +{ + m_resolution = sz; +} + +size_t +EditableDenseThreeDimensionalModel::getYBinCount() const +{ + return m_yBinCount; +} + +void +EditableDenseThreeDimensionalModel::setYBinCount(size_t sz) +{ + m_yBinCount = sz; +} + +float +EditableDenseThreeDimensionalModel::getMinimumLevel() const +{ + return m_minimum; +} + +void +EditableDenseThreeDimensionalModel::setMinimumLevel(float level) +{ + m_minimum = level; +} + +float +EditableDenseThreeDimensionalModel::getMaximumLevel() const +{ + return m_maximum; +} + +void +EditableDenseThreeDimensionalModel::setMaximumLevel(float level) +{ + m_maximum = level; +} + +void +EditableDenseThreeDimensionalModel::getBinValues(long windowStart, + BinValueSet &result) const +{ + QMutexLocker locker(&m_mutex); + + long index = windowStart / m_resolution; + + if (index >= 0 && index < long(m_data.size())) { + result = m_data[index]; + } else { + result.clear(); + } + + while (result.size() < m_yBinCount) result.push_back(m_minimum); +} + +float +EditableDenseThreeDimensionalModel::getBinValue(long windowStart, + size_t n) const +{ + QMutexLocker locker(&m_mutex); + + long index = windowStart / m_resolution; + + if (index >= 0 && index < long(m_data.size())) { + const BinValueSet &s = m_data[index]; + if (n < s.size()) return s[n]; + } + + return m_minimum; +} + +void +EditableDenseThreeDimensionalModel::setBinValues(long windowStart, + const BinValueSet &values) +{ + QMutexLocker locker(&m_mutex); + + long index = windowStart / m_resolution; + + while (index >= long(m_data.size())) { + m_data.push_back(BinValueSet()); + } + + bool newExtents = (m_data.empty() && (m_minimum == m_maximum)); + bool allChange = false; + + for (size_t i = 0; i < values.size(); ++i) { + if (newExtents || values[i] < m_minimum) { + m_minimum = values[i]; + allChange = true; + } + if (newExtents || values[i] > m_maximum) { + m_maximum = values[i]; + allChange = true; + } + } + + m_data[index] = values; + + if (m_notifyOnAdd) { + if (allChange) { + emit modelChanged(); + } else { + emit modelChanged(windowStart, windowStart + m_resolution); + } + } else { + if (allChange) { + m_sinceLastNotifyMin = -1; + m_sinceLastNotifyMax = -1; + emit modelChanged(); + } else { + if (m_sinceLastNotifyMin == -1 || + windowStart < m_sinceLastNotifyMin) { + m_sinceLastNotifyMin = windowStart; + } + if (m_sinceLastNotifyMax == -1 || + windowStart > m_sinceLastNotifyMax) { + m_sinceLastNotifyMax = windowStart; + } + } + } +} + +QString +EditableDenseThreeDimensionalModel::getBinName(size_t n) const +{ + if (m_binNames.size() > n) return m_binNames[n]; + else return ""; +} + +void +EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name) +{ + while (m_binNames.size() <= n) m_binNames.push_back(""); + m_binNames[n] = name; + emit modelChanged(); +} + +void +EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names) +{ + m_binNames = names; + emit modelChanged(); +} + +void +EditableDenseThreeDimensionalModel::setCompletion(int completion) +{ + if (m_completion != completion) { + m_completion = completion; + + if (completion == 100) { + + m_notifyOnAdd = true; // henceforth + emit modelChanged(); + + } else if (!m_notifyOnAdd) { + + if (m_sinceLastNotifyMin >= 0 && + m_sinceLastNotifyMax >= 0) { + emit modelChanged(m_sinceLastNotifyMin, + m_sinceLastNotifyMax + m_resolution); + m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; + } else { + emit completionChanged(); + } + } else { + emit completionChanged(); + } + } +} + +void +EditableDenseThreeDimensionalModel::toXml(QTextStream &out, + QString indent, + QString extraAttributes) const +{ + // For historical reasons we read and write "resolution" as "windowSize" + + out << Model::toXmlString + (indent, QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6") + .arg(m_resolution) + .arg(m_yBinCount) + .arg(m_minimum) + .arg(m_maximum) + .arg(getObjectExportId(&m_data)) + .arg(extraAttributes)); + + out << indent; + out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n") + .arg(getObjectExportId(&m_data)); + + for (size_t i = 0; i < m_binNames.size(); ++i) { + if (m_binNames[i] != "") { + out << indent + " "; + out << QString("<bin number=\"%1\" name=\"%2\"/>\n") + .arg(i).arg(m_binNames[i]); + } + } + + for (size_t i = 0; i < m_data.size(); ++i) { + out << indent + " "; + out << QString("<row n=\"%1\">").arg(i); + for (size_t j = 0; j < m_data[i].size(); ++j) { + if (j > 0) out << " "; + out << m_data[i][j]; + } + out << QString("</row>\n"); + } + + out << indent + "</dataset>\n"; +} + +QString +EditableDenseThreeDimensionalModel::toXmlString(QString indent, + QString extraAttributes) const +{ + QString s; + + { + QTextStream out(&s); + toXml(out, indent, extraAttributes); + } + + return s; +} + +#ifdef INCLUDE_MOCFILES +#include "EditableDenseThreeDimensionalModel.moc.cpp" +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/EditableDenseThreeDimensionalModel.h Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,132 @@ +/* -*- 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 _EDITABLE_DENSE_THREE_DIMENSIONAL_MODEL_H_ +#define _EDITABLE_DENSE_THREE_DIMENSIONAL_MODEL_H_ + +#include "DenseThreeDimensionalModel.h" + +class EditableDenseThreeDimensionalModel : public DenseThreeDimensionalModel +{ + Q_OBJECT + +public: + EditableDenseThreeDimensionalModel(size_t sampleRate, + size_t resolution, + size_t yBinCount, + bool notifyOnAdd = true); + + virtual bool isOK() const; + + virtual size_t getSampleRate() const; + virtual size_t getStartFrame() const; + virtual size_t getEndFrame() const; + + virtual Model *clone() const; + + + /** + * Return the number of sample frames covered by each set of bins. + */ + virtual size_t getResolution() const; + + /** + * Set the number of sample frames covered by each set of bins. + */ + virtual void setResolution(size_t sz); + + /** + * Return the number of bins in each set of bins. + */ + virtual size_t getYBinCount() const; + + /** + * Set the number of bins in each set of bins. + */ + virtual void setYBinCount(size_t sz); + + /** + * Return the minimum value of the value in each bin. + */ + virtual float getMinimumLevel() const; + + /** + * Set the minimum value of the value in a bin. + */ + virtual void setMinimumLevel(float sz); + + /** + * Return the maximum value of the value in each bin. + */ + virtual float getMaximumLevel() const; + + /** + * Set the maximum value of the value in a bin. + */ + virtual void setMaximumLevel(float sz); + + typedef std::vector<float> BinValueSet; + + /** + * Get the set of bin values at the given sample frame (i.e. the + * windowStartFrame/getResolution()'th set of bins). + */ + virtual void getBinValues(long windowStartFrame, BinValueSet &result) const; + + /** + * Get a single value, the one at the n'th bin of the set of bins + * starting at the given sample frame. + */ + virtual float getBinValue(long windowStartFrame, size_t n) const; + + /** + * Set the entire set of bin values at the given sample frame. + */ + virtual void setBinValues(long windowStartFrame, const BinValueSet &values); + + virtual QString getBinName(size_t n) const; + virtual void setBinName(size_t n, QString); + virtual void setBinNames(std::vector<QString> names); + + virtual void setCompletion(int completion); + virtual int getCompletion() const { return m_completion; } + + virtual void toXml(QTextStream &out, + QString indent = "", + QString extraAttributes = "") const; + + virtual QString toXmlString(QString indent = "", + QString extraAttributes = "") const; + +protected: + typedef std::vector<BinValueSet> ValueMatrix; + ValueMatrix m_data; + + std::vector<QString> m_binNames; + + size_t m_sampleRate; + size_t m_resolution; + size_t m_yBinCount; + float m_minimum; + float m_maximum; + bool m_notifyOnAdd; + long m_sinceLastNotifyMin; + long m_sinceLastNotifyMax; + int m_completion; + + mutable QMutex m_mutex; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/FFTModel.cpp Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,126 @@ +/* -*- 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 "FFTModel.h" +#include "DenseTimeValueModel.h" + +#include <cassert> + +FFTModel::FFTModel(const DenseTimeValueModel *model, + int channel, + WindowType windowType, + size_t windowSize, + size_t windowIncrement, + size_t fftSize, + bool polar, + size_t fillFromColumn) : + //!!! ZoomConstraint! + m_server(0), + m_xshift(0), + m_yshift(0) +{ + m_server = FFTDataServer::getFuzzyInstance(model, + channel, + windowType, + windowSize, + windowIncrement, + fftSize, + polar, + fillFromColumn); + + size_t xratio = windowIncrement / m_server->getWindowIncrement(); + size_t yratio = m_server->getFFTSize() / fftSize; + + while (xratio > 1) { + if (xratio & 0x1) { + std::cerr << "ERROR: FFTModel: Window increment ratio " + << windowIncrement << " / " + << m_server->getWindowIncrement() + << " must be a power of two" << std::endl; + assert(!(xratio & 0x1)); + } + ++m_xshift; + xratio >>= 1; + } + + while (yratio > 1) { + if (yratio & 0x1) { + std::cerr << "ERROR: FFTModel: FFT size ratio " + << m_server->getFFTSize() << " / " << fftSize + << " must be a power of two" << std::endl; + assert(!(yratio & 0x1)); + } + ++m_yshift; + yratio >>= 1; + } +} + +FFTModel::~FFTModel() +{ + FFTDataServer::releaseInstance(m_server); +} + +size_t +FFTModel::getSampleRate() const +{ + return isOK() ? m_server->getModel()->getSampleRate() : 0; +} + +void +FFTModel::getBinValues(long windowStartFrame, BinValueSet &result) const +{ + if (windowStartFrame < 0) windowStartFrame = 0; + size_t x = windowStartFrame / getResolution(); + result.clear(); + size_t height(getHeight()); + for (size_t y = 0; y < height; ++y) { + result.push_back(const_cast<FFTModel *>(this)->getMagnitudeAt(x, y)); + } +} + +float +FFTModel::getBinValue(long windowStartFrame, size_t n) const +{ + if (windowStartFrame < 0) windowStartFrame = 0; + size_t x = windowStartFrame / getResolution(); + return const_cast<FFTModel *>(this)->getMagnitudeAt(x, n); +} + +QString +FFTModel::getBinName(size_t n) const +{ + size_t sr = getSampleRate(); + if (!sr) return ""; + QString name = tr("%1 Hz").arg((n * sr) / (getHeight() * 2)); + return name; +} + +Model * +FFTModel::clone() const +{ + return new FFTModel(*this); +} + +FFTModel::FFTModel(const FFTModel &model) : + QObject(), + ZoomConstraint(), //!!! want a real ZoomConstraint for this! + DenseThreeDimensionalModel(), + m_server(model.m_server), + m_xshift(model.m_xshift), + m_yshift(model.m_yshift) +{ + FFTDataServer::claimInstance(m_server); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/FFTModel.h Mon Jul 31 17:05:18 2006 +0000 @@ -0,0 +1,112 @@ +/* -*- 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_MODEL_H_ +#define _FFT_MODEL_H_ + +#include "data/fft/FFTDataServer.h" +#include "DenseThreeDimensionalModel.h" + +class FFTModel : public DenseThreeDimensionalModel +{ +public: + FFTModel(const DenseTimeValueModel *model, + int channel, + WindowType windowType, + size_t windowSize, + size_t windowIncrement, + size_t fftSize, + bool polar, + size_t fillFromColumn = 0); + ~FFTModel(); + + size_t getWidth() const { + return m_server->getWidth() >> m_xshift; + } + size_t getHeight() const { + return m_server->getHeight() >> m_yshift; + } + float getMagnitudeAt(size_t x, size_t y) { + return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift); + } + float getNormalizedMagnitudeAt(size_t x, size_t y) { + return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift); + } + float getMaximumMagnitudeAt(size_t x) { + return m_server->getMaximumMagnitudeAt(x << m_xshift); + } + float getPhaseAt(size_t x, size_t y) { + return m_server->getPhaseAt(x << m_xshift, y << m_yshift); + } + void getValuesAt(size_t x, size_t y, float &real, float &imaginary) { + m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary); + } + bool isColumnReady(size_t x) { + return m_server->isColumnReady(x << m_xshift); + } + bool isLocalPeak(size_t x, size_t y) { + float mag = getMagnitudeAt(x, y); + if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false; + if (y < getHeight() - 1 && mag < getMagnitudeAt(x, y + 1)) return false; + return true; + } + bool isOverThreshold(size_t x, size_t y, float threshold) { + return getMagnitudeAt(x, y) > threshold; + } + + size_t getFillExtent() const { return m_server->getFillExtent(); } + + // DenseThreeDimensionalModel and Model methods: + // + virtual bool isOK() const { + return m_server && m_server->getModel(); + } + virtual size_t getStartFrame() const { + return 0; + } + virtual size_t getEndFrame() const { + return getWidth() * getResolution() + getResolution(); + } + virtual size_t getSampleRate() const; + virtual size_t getResolution() const { + return m_server->getWindowIncrement() << m_xshift; + } + virtual size_t getYBinCount() const { + return getHeight(); + } + virtual float getMinimumLevel() const { + return 0.f; // Can't provide + } + virtual float getMaximumLevel() const { + return 1.f; // Can't provide + } + virtual void getBinValues(long windowStartFrame, BinValueSet &result) const; + virtual float getBinValue(long windowStartFrame, size_t n) const; + virtual QString getBinName(size_t n) const; + + virtual int getCompletion() const { return m_server->getFillCompletion(); } + + virtual Model *clone() const; + +private: + FFTModel(const FFTModel &); + FFTModel &operator=(const FFTModel &); // not implemented + + FFTDataServer *m_server; + int m_xshift; + int m_yshift; +}; + +#endif