annotate data/fft/FFTFileCache.cpp @ 382:9867f99e0bb7 sv1-v1.2

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