00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00028
00029
00030
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
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
00235
00236
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
00288
00289
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);
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