annotate data/fft/FFTFileCacheReader.cpp @ 550:107d3f3705c9

* Auto-close write-mode matrix files when all columns written
author Chris Cannam
date Thu, 05 Feb 2009 14:17:11 +0000
parents 3cc4b7cd2aa5
children 60482f13e627
rev   line source
Chris@537 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@537 2
Chris@537 3 /*
Chris@537 4 Sonic Visualiser
Chris@537 5 An audio file viewer and annotation editor.
Chris@537 6 Centre for Digital Music, Queen Mary, University of London.
Chris@537 7 This file copyright 2006-2009 Chris Cannam and QMUL.
Chris@537 8
Chris@537 9 This program is free software; you can redistribute it and/or
Chris@537 10 modify it under the terms of the GNU General Public License as
Chris@537 11 published by the Free Software Foundation; either version 2 of the
Chris@537 12 License, or (at your option) any later version. See the file
Chris@537 13 COPYING included with this distribution for more information.
Chris@537 14 */
Chris@537 15
Chris@537 16 #include "FFTFileCacheReader.h"
Chris@537 17 #include "FFTFileCacheWriter.h"
Chris@537 18
Chris@537 19 #include "fileio/MatrixFile.h"
Chris@537 20
Chris@537 21 #include "base/Profiler.h"
Chris@537 22 #include "base/Thread.h"
Chris@537 23 #include "base/Exceptions.h"
Chris@537 24
Chris@537 25 #include <iostream>
Chris@537 26
Chris@537 27
Chris@537 28 // The underlying matrix has height (m_height * 2 + 1). In each
Chris@537 29 // column we store magnitude at [0], [2] etc and phase at [1], [3]
Chris@537 30 // etc, and then store the normalization factor (maximum magnitude) at
Chris@537 31 // [m_height * 2]. In compact mode, the factor takes two cells.
Chris@537 32
Chris@537 33 FFTFileCacheReader::FFTFileCacheReader(FFTFileCacheWriter *writer) :
Chris@537 34 m_readbuf(0),
Chris@537 35 m_readbufCol(0),
Chris@537 36 m_readbufWidth(0),
Chris@537 37 m_storageType(writer->getStorageType()),
Chris@537 38 m_factorSize(m_storageType == FFTCache::Compact ? 2 : 1),
Chris@537 39 m_mfc(new MatrixFile
Chris@537 40 (writer->getFileBase(),
Chris@537 41 MatrixFile::ReadOnly,
Chris@537 42 m_storageType == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float),
Chris@537 43 writer->getWidth(),
Chris@537 44 writer->getHeight() * 2 + m_factorSize))
Chris@537 45 {
Chris@537 46 // std::cerr << "FFTFileCacheReader: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
Chris@537 47 }
Chris@537 48
Chris@537 49 FFTFileCacheReader::~FFTFileCacheReader()
Chris@537 50 {
Chris@537 51 if (m_readbuf) delete[] m_readbuf;
Chris@537 52 delete m_mfc;
Chris@537 53 }
Chris@537 54
Chris@537 55 size_t
Chris@537 56 FFTFileCacheReader::getWidth() const
Chris@537 57 {
Chris@537 58 return m_mfc->getWidth();
Chris@537 59 }
Chris@537 60
Chris@537 61 size_t
Chris@537 62 FFTFileCacheReader::getHeight() const
Chris@537 63 {
Chris@537 64 size_t mh = m_mfc->getHeight();
Chris@537 65 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
Chris@537 66 else return 0;
Chris@537 67 }
Chris@537 68
Chris@537 69 float
Chris@537 70 FFTFileCacheReader::getMagnitudeAt(size_t x, size_t y) const
Chris@537 71 {
Chris@537 72 Profiler profiler("FFTFileCacheReader::getMagnitudeAt", false);
Chris@537 73
Chris@537 74 float value = 0.f;
Chris@537 75
Chris@537 76 switch (m_storageType) {
Chris@537 77
Chris@537 78 case FFTCache::Compact:
Chris@537 79 value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
Chris@537 80 * getNormalizationFactor(x);
Chris@537 81 break;
Chris@537 82
Chris@537 83 case FFTCache::Rectangular:
Chris@537 84 {
Chris@537 85 float real, imag;
Chris@537 86 getValuesAt(x, y, real, imag);
Chris@537 87 value = sqrtf(real * real + imag * imag);
Chris@537 88 break;
Chris@537 89 }
Chris@537 90
Chris@537 91 case FFTCache::Polar:
Chris@537 92 value = getFromReadBufStandard(x, y * 2);
Chris@537 93 break;
Chris@537 94 }
Chris@537 95
Chris@537 96 return value;
Chris@537 97 }
Chris@537 98
Chris@537 99 float
Chris@537 100 FFTFileCacheReader::getNormalizedMagnitudeAt(size_t x, size_t y) const
Chris@537 101 {
Chris@537 102 float value = 0.f;
Chris@537 103
Chris@537 104 switch (m_storageType) {
Chris@537 105
Chris@537 106 case FFTCache::Compact:
Chris@537 107 value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
Chris@537 108 break;
Chris@537 109
Chris@537 110 default:
Chris@537 111 {
Chris@537 112 float mag = getMagnitudeAt(x, y);
Chris@537 113 float factor = getNormalizationFactor(x);
Chris@537 114 if (factor != 0) value = mag / factor;
Chris@537 115 else value = 0.f;
Chris@537 116 break;
Chris@537 117 }
Chris@537 118 }
Chris@537 119
Chris@537 120 return value;
Chris@537 121 }
Chris@537 122
Chris@537 123 float
Chris@537 124 FFTFileCacheReader::getMaximumMagnitudeAt(size_t x) const
Chris@537 125 {
Chris@537 126 return getNormalizationFactor(x);
Chris@537 127 }
Chris@537 128
Chris@537 129 float
Chris@537 130 FFTFileCacheReader::getPhaseAt(size_t x, size_t y) const
Chris@537 131 {
Chris@537 132 float value = 0.f;
Chris@537 133
Chris@537 134 switch (m_storageType) {
Chris@537 135
Chris@537 136 case FFTCache::Compact:
Chris@537 137 value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
Chris@537 138 break;
Chris@537 139
Chris@537 140 case FFTCache::Rectangular:
Chris@537 141 {
Chris@537 142 float real, imag;
Chris@537 143 getValuesAt(x, y, real, imag);
Chris@537 144 value = atan2f(imag, real);
Chris@537 145 break;
Chris@537 146 }
Chris@537 147
Chris@537 148 case FFTCache::Polar:
Chris@537 149 value = getFromReadBufStandard(x, y * 2 + 1);
Chris@537 150 break;
Chris@537 151 }
Chris@537 152
Chris@537 153 return value;
Chris@537 154 }
Chris@537 155
Chris@537 156 void
Chris@537 157 FFTFileCacheReader::getValuesAt(size_t x, size_t y, float &real, float &imag) const
Chris@537 158 {
Chris@537 159 switch (m_storageType) {
Chris@537 160
Chris@537 161 case FFTCache::Rectangular:
Chris@537 162 real = getFromReadBufStandard(x, y * 2);
Chris@537 163 imag = getFromReadBufStandard(x, y * 2 + 1);
Chris@537 164 return;
Chris@537 165
Chris@537 166 default:
Chris@537 167 float mag = getMagnitudeAt(x, y);
Chris@537 168 float phase = getPhaseAt(x, y);
Chris@537 169 real = mag * cosf(phase);
Chris@537 170 imag = mag * sinf(phase);
Chris@537 171 return;
Chris@537 172 }
Chris@537 173 }
Chris@537 174
Chris@537 175 void
Chris@537 176 FFTFileCacheReader::getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) const
Chris@537 177 {
Chris@537 178 Profiler profiler("FFTFileCacheReader::getMagnitudesAt");
Chris@537 179
Chris@537 180 switch (m_storageType) {
Chris@537 181
Chris@537 182 case FFTCache::Compact:
Chris@537 183 for (size_t i = 0; i < count; ++i) {
Chris@537 184 size_t y = minbin + i * step;
Chris@537 185 values[i] = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
Chris@537 186 * getNormalizationFactor(x);
Chris@537 187 }
Chris@537 188 break;
Chris@537 189
Chris@537 190 case FFTCache::Rectangular:
Chris@537 191 {
Chris@537 192 float real, imag;
Chris@537 193 for (size_t i = 0; i < count; ++i) {
Chris@537 194 size_t y = minbin + i * step;
Chris@537 195 real = getFromReadBufStandard(x, y * 2);
Chris@537 196 imag = getFromReadBufStandard(x, y * 2 + 1);
Chris@537 197 values[i] = sqrtf(real * real + imag * imag);
Chris@537 198 }
Chris@537 199 break;
Chris@537 200 }
Chris@537 201
Chris@537 202 case FFTCache::Polar:
Chris@537 203 for (size_t i = 0; i < count; ++i) {
Chris@537 204 size_t y = minbin + i * step;
Chris@537 205 values[i] = getFromReadBufStandard(x, y * 2);
Chris@537 206 }
Chris@537 207 break;
Chris@537 208 }
Chris@537 209 }
Chris@537 210
Chris@537 211 bool
Chris@537 212 FFTFileCacheReader::haveSetColumnAt(size_t x) const
Chris@537 213 {
Chris@537 214 return m_mfc->haveSetColumnAt(x);
Chris@537 215 }
Chris@537 216
Chris@537 217 size_t
Chris@537 218 FFTFileCacheReader::getCacheSize(size_t width, size_t height,
Chris@537 219 FFTCache::StorageType type)
Chris@537 220 {
Chris@537 221 return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
Chris@537 222 (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
Chris@537 223 2 * sizeof(size_t); // matrix file header size
Chris@537 224 }
Chris@537 225
Chris@537 226 void
Chris@537 227 FFTFileCacheReader::populateReadBuf(size_t x) const
Chris@537 228 {
Chris@537 229 Profiler profiler("FFTFileCacheReader::populateReadBuf", false);
Chris@537 230
Chris@537 231 if (!m_readbuf) {
Chris@537 232 m_readbuf = new char[m_mfc->getHeight() * 2 * m_mfc->getCellSize()];
Chris@537 233 }
Chris@537 234
Chris@537 235 try {
Chris@537 236 m_mfc->getColumnAt(x, m_readbuf);
Chris@537 237 if (m_mfc->haveSetColumnAt(x + 1)) {
Chris@537 238 m_mfc->getColumnAt
Chris@537 239 (x + 1, m_readbuf + m_mfc->getCellSize() * m_mfc->getHeight());
Chris@537 240 m_readbufWidth = 2;
Chris@537 241 } else {
Chris@537 242 m_readbufWidth = 1;
Chris@537 243 }
Chris@537 244 } catch (FileReadFailed f) {
Chris@537 245 std::cerr << "ERROR: FFTFileCacheReader::populateReadBuf: File read failed: "
Chris@537 246 << f.what() << std::endl;
Chris@537 247 memset(m_readbuf, 0, m_mfc->getHeight() * 2 * m_mfc->getCellSize());
Chris@537 248 }
Chris@537 249 m_readbufCol = x;
Chris@537 250 }
Chris@537 251