FFTFileCache.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "FFTFileCache.h"
00017 
00018 #include "fileio/MatrixFile.h"
00019 
00020 #include "base/Profiler.h"
00021 
00022 #include <iostream>
00023 
00024 #include <QMutexLocker>
00025 
00026 
00027 // The underlying matrix has height (m_height * 2 + 1).  In each
00028 // column we store magnitude at [0], [2] etc and phase at [1], [3]
00029 // etc, and then store the normalization factor (maximum magnitude) at
00030 // [m_height * 2].  In compact mode, the factor takes two cells.
00031 
00032 FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode,
00033                            StorageType storageType) :
00034     m_writebuf(0),
00035     m_readbuf(0),
00036     m_readbufCol(0),
00037     m_readbufWidth(0),
00038     m_mfc(new MatrixFile
00039           (fileBase, mode, 
00040            storageType == Compact ? sizeof(uint16_t) : sizeof(float),
00041            mode == MatrixFile::ReadOnly)),
00042     m_storageType(storageType),
00043     m_factorSize(storageType == Compact ? 2 : 1)
00044 {
00045 //    std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
00046 }
00047 
00048 FFTFileCache::~FFTFileCache()
00049 {
00050     if (m_readbuf) delete[] m_readbuf;
00051     if (m_writebuf) delete[] m_writebuf;
00052     delete m_mfc;
00053 }
00054 
00055 size_t
00056 FFTFileCache::getWidth() const
00057 {
00058     return m_mfc->getWidth();
00059 }
00060 
00061 size_t
00062 FFTFileCache::getHeight() const
00063 {
00064     size_t mh = m_mfc->getHeight();
00065     if (mh > m_factorSize) return (mh - m_factorSize) / 2;
00066     else return 0;
00067 }
00068 
00069 void
00070 FFTFileCache::resize(size_t width, size_t height)
00071 {
00072     QMutexLocker locker(&m_writeMutex);
00073 
00074     m_mfc->resize(width, height * 2 + m_factorSize);
00075     if (m_readbuf) {
00076         delete[] m_readbuf;
00077         m_readbuf = 0;
00078     }
00079     if (m_writebuf) {
00080         delete[] m_writebuf;
00081     }
00082     m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
00083 }
00084 
00085 void
00086 FFTFileCache::reset()
00087 {
00088     m_mfc->reset();
00089 }
00090 
00091 float
00092 FFTFileCache::getMagnitudeAt(size_t x, size_t y) const
00093 {
00094     Profiler profiler("FFTFileCache::getMagnitudeAt", false);
00095 
00096     float value = 0.f;
00097 
00098     switch (m_storageType) {
00099 
00100     case Compact:
00101         value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
00102             * getNormalizationFactor(x);
00103         break;
00104 
00105     case Rectangular:
00106     {
00107         float real, imag;
00108         getValuesAt(x, y, real, imag);
00109         value = sqrtf(real * real + imag * imag);
00110         break;
00111     }
00112 
00113     case Polar:
00114         value = getFromReadBufStandard(x, y * 2);
00115         break;
00116     }
00117 
00118     return value;
00119 }
00120 
00121 float
00122 FFTFileCache::getNormalizedMagnitudeAt(size_t x, size_t y) const
00123 {
00124     float value = 0.f;
00125 
00126     switch (m_storageType) {
00127 
00128     case Compact:
00129         value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
00130         break;
00131 
00132     default:
00133     {
00134         float mag = getMagnitudeAt(x, y);
00135         float factor = getNormalizationFactor(x);
00136         if (factor != 0) value = mag / factor;
00137         else value = 0.f;
00138         break;
00139     }
00140     }
00141 
00142     return value;
00143 }
00144 
00145 float
00146 FFTFileCache::getMaximumMagnitudeAt(size_t x) const
00147 {
00148     return getNormalizationFactor(x);
00149 }
00150 
00151 float
00152 FFTFileCache::getPhaseAt(size_t x, size_t y) const
00153 {
00154     float value = 0.f;
00155     
00156     switch (m_storageType) {
00157 
00158     case Compact:
00159         value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
00160         break;
00161 
00162     case Rectangular:
00163     {
00164         float real, imag;
00165         getValuesAt(x, y, real, imag);
00166         value = princargf(atan2f(imag, real));
00167         break;
00168     }
00169 
00170     case Polar:
00171         value = getFromReadBufStandard(x, y * 2 + 1);
00172         break;
00173     }
00174 
00175     return value;
00176 }
00177 
00178 void
00179 FFTFileCache::getValuesAt(size_t x, size_t y, float &real, float &imag) const
00180 {
00181     switch (m_storageType) {
00182 
00183     case Rectangular:
00184         real = getFromReadBufStandard(x, y * 2);
00185         imag = getFromReadBufStandard(x, y * 2 + 1);
00186         return;
00187 
00188     default:
00189         float mag = getMagnitudeAt(x, y);
00190         float phase = getPhaseAt(x, y);
00191         real = mag * cosf(phase);
00192         imag = mag * sinf(phase);
00193         return;
00194     }
00195 }
00196 
00197 bool
00198 FFTFileCache::haveSetColumnAt(size_t x) const
00199 {
00200     return m_mfc->haveSetColumnAt(x);
00201 }
00202 
00203 void
00204 FFTFileCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
00205 {
00206     QMutexLocker locker(&m_writeMutex);
00207 
00208     size_t h = getHeight();
00209 
00210     switch (m_storageType) {
00211 
00212     case Compact:
00213         for (size_t y = 0; y < h; ++y) {
00214             ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
00215             ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
00216         }
00217         break;
00218 
00219     case Rectangular:
00220         for (size_t y = 0; y < h; ++y) {
00221             ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
00222             ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
00223         }
00224         break;
00225 
00226     case Polar:
00227         for (size_t y = 0; y < h; ++y) {
00228             ((float *)m_writebuf)[y * 2] = mags[y];
00229             ((float *)m_writebuf)[y * 2 + 1] = phases[y];
00230         }
00231         break;
00232     }
00233 
00234 //    static float maxFactor = 0;
00235 //    if (factor > maxFactor) maxFactor = factor;
00236 //    std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
00237 
00238     setNormalizationFactorToWritebuf(factor);
00239 
00240     m_mfc->setColumnAt(x, m_writebuf);
00241 }
00242 
00243 void
00244 FFTFileCache::setColumnAt(size_t x, float *real, float *imag)
00245 {
00246     QMutexLocker locker(&m_writeMutex);
00247 
00248     size_t h = getHeight();
00249 
00250     float factor = 0.0f;
00251 
00252     switch (m_storageType) {
00253 
00254     case Compact:
00255         for (size_t y = 0; y < h; ++y) {
00256             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00257             if (mag > factor) factor = mag;
00258         }
00259         for (size_t y = 0; y < h; ++y) {
00260             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00261             float phase = princargf(atan2f(imag[y], real[y]));
00262             ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
00263             ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
00264         }
00265         break;
00266 
00267     case Rectangular:
00268         for (size_t y = 0; y < h; ++y) {
00269             ((float *)m_writebuf)[y * 2] = real[y];
00270             ((float *)m_writebuf)[y * 2 + 1] = imag[y];
00271             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00272             if (mag > factor) factor = mag;
00273         }
00274         break;
00275 
00276     case Polar:
00277         for (size_t y = 0; y < h; ++y) {
00278             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00279             if (mag > factor) factor = mag;
00280             ((float *)m_writebuf)[y * 2] = mag;
00281             float phase = princargf(atan2f(imag[y], real[y]));
00282             ((float *)m_writebuf)[y * 2 + 1] = phase;
00283         }
00284         break;
00285     }
00286 
00287 //    static float maxFactor = 0;
00288 //    if (factor > maxFactor) maxFactor = factor;
00289 //    std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
00290 
00291     setNormalizationFactorToWritebuf(factor);
00292 
00293     m_mfc->setColumnAt(x, m_writebuf);
00294 }
00295 
00296 size_t
00297 FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type)
00298 {
00299     return (height * 2 + (type == Compact ? 2 : 1)) * width *
00300         (type == Compact ? sizeof(uint16_t) : sizeof(float)) +
00301         2 * sizeof(size_t); // matrix file header size
00302 }
00303 
00304 void
00305 FFTFileCache::populateReadBuf(size_t x) const
00306 {
00307     Profiler profiler("FFTFileCache::populateReadBuf", false);
00308 
00309     if (!m_readbuf) {
00310         m_readbuf = new char[m_mfc->getHeight() * 2 * m_mfc->getCellSize()];
00311     }
00312     m_mfc->getColumnAt(x, m_readbuf);
00313     if (m_mfc->haveSetColumnAt(x + 1)) {
00314         m_mfc->getColumnAt
00315             (x + 1, m_readbuf + m_mfc->getCellSize() * m_mfc->getHeight());
00316         m_readbufWidth = 2;
00317     } else {
00318         m_readbufWidth = 1;
00319     }
00320     m_readbufCol = x;
00321 }
00322 

Generated on Wed Feb 20 15:45:25 2008 for SonicVisualiser by  doxygen 1.5.1