Mercurial > hg > svcore
diff data/fileio/FFTFileCache.cpp @ 148:1a42221a1522
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 11:49:58 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/fileio/FFTFileCache.cpp Mon Jul 31 11:49:58 2006 +0000 @@ -0,0 +1,288 @@ +/* -*- 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 "FFTFileCache.h" + +#include "MatrixFile.h" + +#include "base/Profiler.h" + +#include <iostream> + +#include <QMutexLocker> + +// The underlying matrix has height (m_height * 2 + 1). In each +// column we store magnitude at [0], [2] etc and phase at [1], [3] +// etc, and then store the normalization factor (maximum magnitude) at +// [m_height * 2]. + +FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode, + StorageType storageType) : + m_writebuf(0), + m_readbuf(0), + m_readbufCol(0), + m_readbufWidth(0), + m_mfc(new MatrixFile + (fileBase, mode, + storageType == Compact ? sizeof(uint16_t) : sizeof(float), + mode == MatrixFile::ReadOnly)), + m_storageType(storageType) +{ + std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl; +} + +FFTFileCache::~FFTFileCache() +{ + if (m_readbuf) delete[] m_readbuf; + if (m_writebuf) delete[] m_writebuf; + delete m_mfc; +} + +size_t +FFTFileCache::getWidth() const +{ + return m_mfc->getWidth(); +} + +size_t +FFTFileCache::getHeight() const +{ + size_t mh = m_mfc->getHeight(); + if (mh > 0) return (mh - 1) / 2; + else return 0; +} + +void +FFTFileCache::resize(size_t width, size_t height) +{ + QMutexLocker locker(&m_writeMutex); + + m_mfc->resize(width, height * 2 + 1); + if (m_readbuf) { + delete[] m_readbuf; + m_readbuf = 0; + } + if (m_writebuf) { + delete[] m_writebuf; + } + m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()]; +} + +void +FFTFileCache::reset() +{ + m_mfc->reset(); +} + +float +FFTFileCache::getMagnitudeAt(size_t x, size_t y) const +{ + float value = 0.f; + + switch (m_storageType) { + + case Compact: + value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0) + * getNormalizationFactor(x); + break; + + case Rectangular: + { + float real, imag; + getValuesAt(x, y, real, imag); + value = sqrtf(real * real + imag * imag); + break; + } + + case Polar: + value = getFromReadBufStandard(x, y * 2); + break; + } + + return value; +} + +float +FFTFileCache::getNormalizedMagnitudeAt(size_t x, size_t y) const +{ + float value = 0.f; + + switch (m_storageType) { + + case Compact: + value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0; + break; + + default: + { + float mag = getMagnitudeAt(x, y); + float factor = getNormalizationFactor(x); + if (factor != 0) value = mag / factor; + else value = 0.f; + break; + } + } + + return value; +} + +float +FFTFileCache::getMaximumMagnitudeAt(size_t x) const +{ + return getNormalizationFactor(x); +} + +float +FFTFileCache::getPhaseAt(size_t x, size_t y) const +{ + float value = 0.f; + + switch (m_storageType) { + + case Compact: + value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI; + break; + + case Rectangular: + { + float real, imag; + getValuesAt(x, y, real, imag); + value = princargf(atan2f(imag, real)); + break; + } + + case Polar: + value = getFromReadBufStandard(x, y * 2 + 1); + break; + } + + return value; +} + +void +FFTFileCache::getValuesAt(size_t x, size_t y, float &real, float &imag) const +{ + switch (m_storageType) { + + case Rectangular: + real = getFromReadBufStandard(x, y * 2); + imag = getFromReadBufStandard(x, y * 2 + 1); + return; + + default: + float mag = getMagnitudeAt(x, y); + float phase = getPhaseAt(x, y); + real = mag * cosf(phase); + imag = mag * sinf(phase); + return; + } +} + +bool +FFTFileCache::haveSetColumnAt(size_t x) const +{ + return m_mfc->haveSetColumnAt(x); +} + +void +FFTFileCache::setColumnAt(size_t x, float *mags, float *phases, float factor) +{ + QMutexLocker locker(&m_writeMutex); + + size_t h = getHeight(); + + switch (m_storageType) { + + case Compact: + for (size_t y = 0; y < h; ++y) { + ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0); + ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI)); + } + break; + + case Rectangular: + for (size_t y = 0; y < h; ++y) { + ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]); + ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]); + } + break; + + case Polar: + for (size_t y = 0; y < h; ++y) { + ((float *)m_writebuf)[y * 2] = mags[y]; + ((float *)m_writebuf)[y * 2 + 1] = phases[y]; + } + break; + } + + static float maxFactor = 0; + if (factor > maxFactor) maxFactor = factor; +// std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl; + + if (m_storageType == Compact) { + ((uint16_t *)m_writebuf)[h * 2] = factor * 65535.0; + } else { + ((float *)m_writebuf)[h * 2] = factor; + } + m_mfc->setColumnAt(x, m_writebuf); +} + +void +FFTFileCache::setColumnAt(size_t x, float *real, float *imag) +{ + QMutexLocker locker(&m_writeMutex); + + size_t h = getHeight(); + + float max = 0.0f; + + switch (m_storageType) { + + case Compact: + for (size_t y = 0; y < h; ++y) { + float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); + if (mag > max) max = mag; + } + for (size_t y = 0; y < h; ++y) { + float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); + float phase = princargf(atan2f(imag[y], real[y])); + ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0); + ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI)); + } + break; + + case Rectangular: + for (size_t y = 0; y < h; ++y) { + ((float *)m_writebuf)[y * 2] = real[y]; + ((float *)m_writebuf)[y * 2 + 1] = imag[y]; + float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); + if (mag > max) max = mag; + } + break; + + case Polar: + for (size_t y = 0; y < h; ++y) { + float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); + if (mag > max) max = mag; + ((float *)m_writebuf)[y * 2] = mag; + ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y])); + } + break; + } + + ((float *)m_writebuf)[h * 2] = max; + m_mfc->setColumnAt(x, m_writebuf); +} +