annotate data/fft/FFTFileCache.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents be6d31baecb9
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam and QMUL.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include <iostream>
lbajardsilogic@0 17
lbajardsilogic@0 18 #include <QMutexLocker>
lbajardsilogic@0 19
lbajardsilogic@191 20 #include "fileio/MatrixFile.h"
lbajardsilogic@191 21 #include "base/Profiler.h"
lbajardsilogic@191 22
lbajardsilogic@191 23 #include "FFTFileCache.h"
lbajardsilogic@191 24
lbajardsilogic@191 25
lbajardsilogic@191 26
lbajardsilogic@191 27
lbajardsilogic@0 28 // The underlying matrix has height (m_height * 2 + 1). In each
lbajardsilogic@0 29 // column we store magnitude at [0], [2] etc and phase at [1], [3]
lbajardsilogic@0 30 // etc, and then store the normalization factor (maximum magnitude) at
lbajardsilogic@0 31 // [m_height * 2].
lbajardsilogic@0 32
lbajardsilogic@0 33 FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode,
lbajardsilogic@0 34 StorageType storageType) :
lbajardsilogic@0 35 m_writebuf(0),
lbajardsilogic@0 36 m_readbuf(0),
lbajardsilogic@0 37 m_readbufCol(0),
lbajardsilogic@0 38 m_readbufWidth(0),
lbajardsilogic@0 39 m_mfc(new MatrixFile
lbajardsilogic@0 40 (fileBase, mode,
lbajardsilogic@0 41 storageType == Compact ? sizeof(uint16_t) : sizeof(float),
lbajardsilogic@0 42 mode == MatrixFile::ReadOnly)),
lbajardsilogic@0 43 m_storageType(storageType)
lbajardsilogic@0 44 {
lbajardsilogic@0 45 // std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
lbajardsilogic@0 46 }
lbajardsilogic@0 47
lbajardsilogic@0 48 FFTFileCache::~FFTFileCache()
lbajardsilogic@0 49 {
lbajardsilogic@0 50 if (m_readbuf) delete[] m_readbuf;
lbajardsilogic@0 51 if (m_writebuf) delete[] m_writebuf;
lbajardsilogic@0 52 delete m_mfc;
lbajardsilogic@0 53 }
lbajardsilogic@0 54
lbajardsilogic@0 55 size_t
lbajardsilogic@0 56 FFTFileCache::getWidth() const
lbajardsilogic@0 57 {
lbajardsilogic@0 58 return m_mfc->getWidth();
lbajardsilogic@0 59 }
lbajardsilogic@0 60
lbajardsilogic@0 61 size_t
lbajardsilogic@0 62 FFTFileCache::getHeight() const
lbajardsilogic@0 63 {
lbajardsilogic@0 64 size_t mh = m_mfc->getHeight();
lbajardsilogic@0 65 if (mh > 0) return (mh - 1) / 2;
lbajardsilogic@0 66 else return 0;
lbajardsilogic@0 67 }
lbajardsilogic@0 68
lbajardsilogic@0 69 void
lbajardsilogic@0 70 FFTFileCache::resize(size_t width, size_t height)
lbajardsilogic@0 71 {
lbajardsilogic@0 72 QMutexLocker locker(&m_writeMutex);
lbajardsilogic@0 73
lbajardsilogic@0 74 m_mfc->resize(width, height * 2 + 1);
lbajardsilogic@0 75 if (m_readbuf) {
lbajardsilogic@0 76 delete[] m_readbuf;
lbajardsilogic@0 77 m_readbuf = 0;
lbajardsilogic@0 78 }
lbajardsilogic@0 79 if (m_writebuf) {
lbajardsilogic@0 80 delete[] m_writebuf;
lbajardsilogic@0 81 }
lbajardsilogic@0 82 m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()];
lbajardsilogic@0 83 }
lbajardsilogic@0 84
lbajardsilogic@0 85 void
lbajardsilogic@0 86 FFTFileCache::reset()
lbajardsilogic@0 87 {
lbajardsilogic@0 88 m_mfc->reset();
lbajardsilogic@0 89 }
lbajardsilogic@0 90
lbajardsilogic@0 91 float
lbajardsilogic@0 92 FFTFileCache::getMagnitudeAt(size_t x, size_t y) const
lbajardsilogic@0 93 {
lbajardsilogic@0 94 Profiler profiler("FFTFileCache::getMagnitudeAt", false);
lbajardsilogic@0 95
lbajardsilogic@0 96 float value = 0.f;
lbajardsilogic@0 97
lbajardsilogic@0 98 switch (m_storageType) {
lbajardsilogic@0 99
lbajardsilogic@0 100 case Compact:
lbajardsilogic@0 101 value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
lbajardsilogic@0 102 * getNormalizationFactor(x);
lbajardsilogic@0 103 break;
lbajardsilogic@0 104
lbajardsilogic@0 105 case Rectangular:
lbajardsilogic@0 106 {
lbajardsilogic@0 107 float real, imag;
lbajardsilogic@0 108 getValuesAt(x, y, real, imag);
lbajardsilogic@0 109 value = sqrtf(real * real + imag * imag);
lbajardsilogic@0 110 break;
lbajardsilogic@0 111 }
lbajardsilogic@0 112
lbajardsilogic@0 113 case Polar:
lbajardsilogic@0 114 value = getFromReadBufStandard(x, y * 2);
lbajardsilogic@0 115 break;
lbajardsilogic@0 116 }
lbajardsilogic@0 117
lbajardsilogic@0 118 return value;
lbajardsilogic@0 119 }
lbajardsilogic@0 120
lbajardsilogic@0 121 float
lbajardsilogic@0 122 FFTFileCache::getNormalizedMagnitudeAt(size_t x, size_t y) const
lbajardsilogic@0 123 {
lbajardsilogic@0 124 float value = 0.f;
lbajardsilogic@0 125
lbajardsilogic@0 126 switch (m_storageType) {
lbajardsilogic@0 127
lbajardsilogic@0 128 case Compact:
lbajardsilogic@0 129 value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
lbajardsilogic@0 130 break;
lbajardsilogic@0 131
lbajardsilogic@0 132 default:
lbajardsilogic@0 133 {
lbajardsilogic@0 134 float mag = getMagnitudeAt(x, y);
lbajardsilogic@0 135 float factor = getNormalizationFactor(x);
lbajardsilogic@0 136 if (factor != 0) value = mag / factor;
lbajardsilogic@0 137 else value = 0.f;
lbajardsilogic@0 138 break;
lbajardsilogic@0 139 }
lbajardsilogic@0 140 }
lbajardsilogic@0 141
lbajardsilogic@0 142 return value;
lbajardsilogic@0 143 }
lbajardsilogic@0 144
lbajardsilogic@0 145 float
lbajardsilogic@0 146 FFTFileCache::getMaximumMagnitudeAt(size_t x) const
lbajardsilogic@0 147 {
lbajardsilogic@0 148 return getNormalizationFactor(x);
lbajardsilogic@0 149 }
lbajardsilogic@0 150
lbajardsilogic@0 151 float
lbajardsilogic@0 152 FFTFileCache::getPhaseAt(size_t x, size_t y) const
lbajardsilogic@0 153 {
lbajardsilogic@0 154 float value = 0.f;
lbajardsilogic@0 155
lbajardsilogic@0 156 switch (m_storageType) {
lbajardsilogic@0 157
lbajardsilogic@0 158 case Compact:
lbajardsilogic@0 159 value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
lbajardsilogic@0 160 break;
lbajardsilogic@0 161
lbajardsilogic@0 162 case Rectangular:
lbajardsilogic@0 163 {
lbajardsilogic@0 164 float real, imag;
lbajardsilogic@0 165 getValuesAt(x, y, real, imag);
lbajardsilogic@0 166 value = princargf(atan2f(imag, real));
lbajardsilogic@0 167 break;
lbajardsilogic@0 168 }
lbajardsilogic@0 169
lbajardsilogic@0 170 case Polar:
lbajardsilogic@0 171 value = getFromReadBufStandard(x, y * 2 + 1);
lbajardsilogic@0 172 break;
lbajardsilogic@0 173 }
lbajardsilogic@0 174
lbajardsilogic@0 175 return value;
lbajardsilogic@0 176 }
lbajardsilogic@0 177
lbajardsilogic@0 178 void
lbajardsilogic@0 179 FFTFileCache::getValuesAt(size_t x, size_t y, float &real, float &imag) const
lbajardsilogic@0 180 {
lbajardsilogic@0 181 switch (m_storageType) {
lbajardsilogic@0 182
lbajardsilogic@0 183 case Rectangular:
lbajardsilogic@0 184 real = getFromReadBufStandard(x, y * 2);
lbajardsilogic@0 185 imag = getFromReadBufStandard(x, y * 2 + 1);
lbajardsilogic@0 186 return;
lbajardsilogic@0 187
lbajardsilogic@0 188 default:
lbajardsilogic@0 189 float mag = getMagnitudeAt(x, y);
lbajardsilogic@0 190 float phase = getPhaseAt(x, y);
lbajardsilogic@0 191 real = mag * cosf(phase);
lbajardsilogic@0 192 imag = mag * sinf(phase);
lbajardsilogic@0 193 return;
lbajardsilogic@0 194 }
lbajardsilogic@0 195 }
lbajardsilogic@0 196
lbajardsilogic@0 197 bool
lbajardsilogic@0 198 FFTFileCache::haveSetColumnAt(size_t x) const
lbajardsilogic@0 199 {
lbajardsilogic@0 200 return m_mfc->haveSetColumnAt(x);
lbajardsilogic@0 201 }
lbajardsilogic@0 202
lbajardsilogic@0 203 void
lbajardsilogic@0 204 FFTFileCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
lbajardsilogic@0 205 {
lbajardsilogic@0 206 QMutexLocker locker(&m_writeMutex);
lbajardsilogic@0 207
lbajardsilogic@0 208 size_t h = getHeight();
lbajardsilogic@0 209
lbajardsilogic@0 210 switch (m_storageType) {
lbajardsilogic@0 211
lbajardsilogic@0 212 case Compact:
lbajardsilogic@0 213 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 214 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
lbajardsilogic@0 215 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
lbajardsilogic@0 216 }
lbajardsilogic@0 217 break;
lbajardsilogic@0 218
lbajardsilogic@0 219 case Rectangular:
lbajardsilogic@0 220 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 221 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
lbajardsilogic@0 222 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
lbajardsilogic@0 223 }
lbajardsilogic@0 224 break;
lbajardsilogic@0 225
lbajardsilogic@0 226 case Polar:
lbajardsilogic@0 227 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 228 ((float *)m_writebuf)[y * 2] = mags[y];
lbajardsilogic@0 229 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
lbajardsilogic@0 230 }
lbajardsilogic@0 231 break;
lbajardsilogic@0 232 }
lbajardsilogic@0 233
lbajardsilogic@0 234 static float maxFactor = 0;
lbajardsilogic@0 235 if (factor > maxFactor) maxFactor = factor;
lbajardsilogic@0 236 // std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
lbajardsilogic@0 237
lbajardsilogic@0 238 if (m_storageType == Compact) {
lbajardsilogic@0 239 if (factor < 0.f || factor > 1.f) {
lbajardsilogic@0 240 std::cerr << "WARNING: FFTFileCache::setColumnAt: Normalization factor " << factor << " out of range" << std::endl;
lbajardsilogic@0 241 if (factor < 0.f) factor = 0.f;
lbajardsilogic@0 242 if (factor > 1.f) factor = 1.f;
lbajardsilogic@0 243 }
lbajardsilogic@0 244 ((uint16_t *)m_writebuf)[h * 2] = (uint16_t)(factor * 65535.0);
lbajardsilogic@0 245 } else {
lbajardsilogic@0 246 ((float *)m_writebuf)[h * 2] = factor;
lbajardsilogic@0 247 }
lbajardsilogic@0 248 m_mfc->setColumnAt(x, m_writebuf);
lbajardsilogic@0 249 }
lbajardsilogic@0 250
lbajardsilogic@0 251 void
lbajardsilogic@0 252 FFTFileCache::setColumnAt(size_t x, float *real, float *imag)
lbajardsilogic@0 253 {
lbajardsilogic@0 254 QMutexLocker locker(&m_writeMutex);
lbajardsilogic@0 255
lbajardsilogic@0 256 size_t h = getHeight();
lbajardsilogic@0 257
lbajardsilogic@0 258 float max = 0.0f;
lbajardsilogic@0 259
lbajardsilogic@0 260 switch (m_storageType) {
lbajardsilogic@0 261
lbajardsilogic@0 262 case Compact:
lbajardsilogic@0 263 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 264 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
lbajardsilogic@0 265 if (mag > max) max = mag;
lbajardsilogic@0 266 }
lbajardsilogic@0 267 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 268 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
lbajardsilogic@0 269 float phase = princargf(atan2f(imag[y], real[y]));
lbajardsilogic@0 270 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0);
lbajardsilogic@0 271 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
lbajardsilogic@0 272 }
lbajardsilogic@0 273 break;
lbajardsilogic@0 274
lbajardsilogic@0 275 case Rectangular:
lbajardsilogic@0 276 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 277 ((float *)m_writebuf)[y * 2] = real[y];
lbajardsilogic@0 278 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
lbajardsilogic@0 279 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
lbajardsilogic@0 280 if (mag > max) max = mag;
lbajardsilogic@0 281 }
lbajardsilogic@0 282 break;
lbajardsilogic@0 283
lbajardsilogic@0 284 case Polar:
lbajardsilogic@0 285 for (size_t y = 0; y < h; ++y) {
lbajardsilogic@0 286 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
lbajardsilogic@0 287 if (mag > max) max = mag;
lbajardsilogic@0 288 ((float *)m_writebuf)[y * 2] = mag;
lbajardsilogic@0 289 ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y]));
lbajardsilogic@0 290 }
lbajardsilogic@0 291 break;
lbajardsilogic@0 292 }
lbajardsilogic@0 293
lbajardsilogic@0 294 ((float *)m_writebuf)[h * 2] = max;
lbajardsilogic@0 295 m_mfc->setColumnAt(x, m_writebuf);
lbajardsilogic@0 296 }
lbajardsilogic@0 297
lbajardsilogic@0 298 size_t
lbajardsilogic@0 299 FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type)
lbajardsilogic@0 300 {
lbajardsilogic@0 301 return (height * 2 + 1) * width *
lbajardsilogic@0 302 (type == Compact ? sizeof(uint16_t) : sizeof(float)) +
lbajardsilogic@0 303 2 * sizeof(size_t); // matrix file header size
lbajardsilogic@0 304 }
lbajardsilogic@0 305
lbajardsilogic@0 306 void
lbajardsilogic@0 307 FFTFileCache::populateReadBuf(size_t x) const
lbajardsilogic@0 308 {
lbajardsilogic@0 309 Profiler profiler("FFTFileCache::populateReadBuf", false);
lbajardsilogic@0 310
lbajardsilogic@0 311 if (!m_readbuf) {
lbajardsilogic@0 312 m_readbuf = new char[m_mfc->getHeight() * 2 * m_mfc->getCellSize()];
lbajardsilogic@0 313 }
lbajardsilogic@0 314 m_mfc->getColumnAt(x, m_readbuf);
lbajardsilogic@0 315 if (m_mfc->haveSetColumnAt(x + 1)) {
lbajardsilogic@0 316 m_mfc->getColumnAt
lbajardsilogic@0 317 (x + 1, m_readbuf + m_mfc->getCellSize() * m_mfc->getHeight());
lbajardsilogic@0 318 m_readbufWidth = 2;
lbajardsilogic@0 319 } else {
lbajardsilogic@0 320 m_readbufWidth = 1;
lbajardsilogic@0 321 }
lbajardsilogic@0 322 m_readbufCol = x;
lbajardsilogic@0 323 }
lbajardsilogic@0 324