annotate data/fileio/FFTFileCache.cpp @ 167:665342c6ec57

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