svcore
1.9
|
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