svcore  1.9
FFTFileCacheWriter.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-2009 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 "FFTFileCacheWriter.h"
00017 
00018 #include "fileio/MatrixFile.h"
00019 
00020 #include "base/Profiler.h"
00021 #include "base/Thread.h"
00022 #include "base/Exceptions.h"
00023 
00024 #include <iostream>
00025 
00026 //#define DEBUG_FFT_FILE_CACHE_WRITER 1
00027 
00028 
00029 // The underlying matrix has height (m_height * 2 + 1).  In each
00030 // column we store magnitude at [0], [2] etc and phase at [1], [3]
00031 // etc, and then store the normalization factor (maximum magnitude) at
00032 // [m_height * 2].  In compact mode, the factor takes two cells.
00033 
00034 FFTFileCacheWriter::FFTFileCacheWriter(QString fileBase,
00035                                        FFTCache::StorageType storageType,
00036                                        int width, int height) :
00037     m_writebuf(0),
00038     m_fileBase(fileBase),
00039     m_storageType(storageType),
00040     m_factorSize(storageType == FFTCache::Compact ? 2 : 1),
00041     m_mfc(new MatrixFile
00042           (fileBase, MatrixFile::WriteOnly, 
00043            storageType == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float),
00044            width, height * 2 + m_factorSize))
00045 {
00046 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
00047     cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << endl;
00048 #endif
00049     m_mfc->setAutoClose(true);
00050     m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
00051 }
00052 
00053 FFTFileCacheWriter::~FFTFileCacheWriter()
00054 {
00055     if (m_writebuf) delete[] m_writebuf;
00056     delete m_mfc;
00057 }
00058 
00059 QString
00060 FFTFileCacheWriter::getFileBase() const
00061 {
00062     return m_fileBase;
00063 }
00064 
00065 int
00066 FFTFileCacheWriter::getWidth() const
00067 {
00068     return m_mfc->getWidth();
00069 }
00070 
00071 int
00072 FFTFileCacheWriter::getHeight() const
00073 {
00074     int mh = m_mfc->getHeight();
00075     if (mh > m_factorSize) return (mh - m_factorSize) / 2;
00076     else return 0;
00077 }
00078 
00079 bool
00080 FFTFileCacheWriter::haveSetColumnAt(int x) const
00081 {
00082     return m_mfc->haveSetColumnAt(x);
00083 }
00084 
00085 void
00086 FFTFileCacheWriter::setColumnAt(int x, float *mags, float *phases, float factor)
00087 {
00088     int h = getHeight();
00089 
00090     switch (m_storageType) {
00091 
00092     case FFTCache::Compact:
00093         for (int y = 0; y < h; ++y) {
00094             ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
00095             ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
00096         }
00097         break;
00098 
00099     case FFTCache::Rectangular:
00100         for (int y = 0; y < h; ++y) {
00101             ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
00102             ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
00103         }
00104         break;
00105 
00106     case FFTCache::Polar:
00107         for (int y = 0; y < h; ++y) {
00108             ((float *)m_writebuf)[y * 2] = mags[y];
00109             ((float *)m_writebuf)[y * 2 + 1] = phases[y];
00110         }
00111         break;
00112     }
00113 
00114     static float maxFactor = 0;
00115     if (factor > maxFactor) maxFactor = factor;
00116 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
00117     cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << endl;
00118 #endif
00119 
00120     setNormalizationFactorToWritebuf(factor);
00121 
00122     m_mfc->setColumnAt(x, m_writebuf);
00123 }
00124 
00125 void
00126 FFTFileCacheWriter::setColumnAt(int x, float *real, float *imag)
00127 {
00128     int h = getHeight();
00129 
00130     float factor = 0.0f;
00131 
00132     switch (m_storageType) {
00133 
00134     case FFTCache::Compact:
00135         for (int y = 0; y < h; ++y) {
00136             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00137             if (mag > factor) factor = mag;
00138         }
00139         for (int y = 0; y < h; ++y) {
00140             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00141             float phase = atan2f(imag[y], real[y]);
00142             ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
00143             ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
00144         }
00145         break;
00146 
00147     case FFTCache::Rectangular:
00148         for (int y = 0; y < h; ++y) {
00149             ((float *)m_writebuf)[y * 2] = real[y];
00150             ((float *)m_writebuf)[y * 2 + 1] = imag[y];
00151             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00152             if (mag > factor) factor = mag;
00153         }
00154         break;
00155 
00156     case FFTCache::Polar:
00157         for (int y = 0; y < h; ++y) {
00158             float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
00159             if (mag > factor) factor = mag;
00160             ((float *)m_writebuf)[y * 2] = mag;
00161             float phase = atan2f(imag[y], real[y]);
00162             ((float *)m_writebuf)[y * 2 + 1] = phase;
00163         }
00164         break;
00165     }
00166 
00167     static float maxFactor = 0;
00168     if (factor > maxFactor) maxFactor = factor;
00169 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
00170     cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << endl;
00171 #endif
00172 
00173     setNormalizationFactorToWritebuf(factor);
00174 
00175     m_mfc->setColumnAt(x, m_writebuf);
00176 }
00177 
00178 int
00179 FFTFileCacheWriter::getCacheSize(int width, int height,
00180                                  FFTCache::StorageType type)
00181 {
00182     return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
00183         (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
00184         2 * sizeof(int); // matrix file header size
00185 }
00186 
00187 void
00188 FFTFileCacheWriter::allColumnsWritten()
00189 {
00190 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
00191     SVDEBUG << "FFTFileCacheWriter::allColumnsWritten" << endl;
00192 #endif
00193     m_mfc->close();
00194 }
00195