annotate data/fft/FFTFileCache.cpp @ 0:fc9323a41f5a

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