annotate data/fft/FFTFileCacheWriter.cpp @ 537:3cc4b7cd2aa5

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +0000
parents
children 107d3f3705c9
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 "FFTFileCacheWriter.h"
Chris@537 17
Chris@537 18 #include "fileio/MatrixFile.h"
Chris@537 19
Chris@537 20 #include "base/Profiler.h"
Chris@537 21 #include "base/Thread.h"
Chris@537 22 #include "base/Exceptions.h"
Chris@537 23
Chris@537 24 #include <iostream>
Chris@537 25
Chris@537 26 //#define DEBUG_FFT_FILE_CACHE_WRITER 1
Chris@537 27
Chris@537 28
Chris@537 29 // The underlying matrix has height (m_height * 2 + 1). In each
Chris@537 30 // column we store magnitude at [0], [2] etc and phase at [1], [3]
Chris@537 31 // etc, and then store the normalization factor (maximum magnitude) at
Chris@537 32 // [m_height * 2]. In compact mode, the factor takes two cells.
Chris@537 33
Chris@537 34 FFTFileCacheWriter::FFTFileCacheWriter(QString fileBase,
Chris@537 35 FFTCache::StorageType storageType,
Chris@537 36 size_t width, size_t height) :
Chris@537 37 m_writebuf(0),
Chris@537 38 m_fileBase(fileBase),
Chris@537 39 m_storageType(storageType),
Chris@537 40 m_factorSize(storageType == FFTCache::Compact ? 2 : 1),
Chris@537 41 m_mfc(new MatrixFile
Chris@537 42 (fileBase, MatrixFile::WriteOnly,
Chris@537 43 storageType == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float),
Chris@537 44 width, height * 2 + m_factorSize))
Chris@537 45 {
Chris@537 46 std::cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << std::endl;
Chris@537 47 m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
Chris@537 48 }
Chris@537 49
Chris@537 50 FFTFileCacheWriter::~FFTFileCacheWriter()
Chris@537 51 {
Chris@537 52 if (m_writebuf) delete[] m_writebuf;
Chris@537 53 delete m_mfc;
Chris@537 54 }
Chris@537 55
Chris@537 56 QString
Chris@537 57 FFTFileCacheWriter::getFileBase() const
Chris@537 58 {
Chris@537 59 return m_fileBase;
Chris@537 60 }
Chris@537 61
Chris@537 62 size_t
Chris@537 63 FFTFileCacheWriter::getWidth() const
Chris@537 64 {
Chris@537 65 return m_mfc->getWidth();
Chris@537 66 }
Chris@537 67
Chris@537 68 size_t
Chris@537 69 FFTFileCacheWriter::getHeight() const
Chris@537 70 {
Chris@537 71 size_t mh = m_mfc->getHeight();
Chris@537 72 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
Chris@537 73 else return 0;
Chris@537 74 }
Chris@537 75
Chris@537 76 void
Chris@537 77 FFTFileCacheWriter::setColumnAt(size_t x, float *mags, float *phases, float factor)
Chris@537 78 {
Chris@537 79 size_t h = getHeight();
Chris@537 80
Chris@537 81 switch (m_storageType) {
Chris@537 82
Chris@537 83 case FFTCache::Compact:
Chris@537 84 for (size_t y = 0; y < h; ++y) {
Chris@537 85 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
Chris@537 86 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
Chris@537 87 }
Chris@537 88 break;
Chris@537 89
Chris@537 90 case FFTCache::Rectangular:
Chris@537 91 for (size_t y = 0; y < h; ++y) {
Chris@537 92 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
Chris@537 93 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
Chris@537 94 }
Chris@537 95 break;
Chris@537 96
Chris@537 97 case FFTCache::Polar:
Chris@537 98 for (size_t y = 0; y < h; ++y) {
Chris@537 99 ((float *)m_writebuf)[y * 2] = mags[y];
Chris@537 100 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
Chris@537 101 }
Chris@537 102 break;
Chris@537 103 }
Chris@537 104
Chris@537 105 static float maxFactor = 0;
Chris@537 106 if (factor > maxFactor) maxFactor = factor;
Chris@537 107 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 108 std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
Chris@537 109 #endif
Chris@537 110
Chris@537 111 setNormalizationFactorToWritebuf(factor);
Chris@537 112
Chris@537 113 m_mfc->setColumnAt(x, m_writebuf);
Chris@537 114 }
Chris@537 115
Chris@537 116 void
Chris@537 117 FFTFileCacheWriter::setColumnAt(size_t x, float *real, float *imag)
Chris@537 118 {
Chris@537 119 size_t h = getHeight();
Chris@537 120
Chris@537 121 float factor = 0.0f;
Chris@537 122
Chris@537 123 switch (m_storageType) {
Chris@537 124
Chris@537 125 case FFTCache::Compact:
Chris@537 126 for (size_t y = 0; y < h; ++y) {
Chris@537 127 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 128 if (mag > factor) factor = mag;
Chris@537 129 }
Chris@537 130 for (size_t y = 0; y < h; ++y) {
Chris@537 131 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 132 float phase = atan2f(imag[y], real[y]);
Chris@537 133 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
Chris@537 134 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@537 135 }
Chris@537 136 break;
Chris@537 137
Chris@537 138 case FFTCache::Rectangular:
Chris@537 139 for (size_t y = 0; y < h; ++y) {
Chris@537 140 ((float *)m_writebuf)[y * 2] = real[y];
Chris@537 141 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
Chris@537 142 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 143 if (mag > factor) factor = mag;
Chris@537 144 }
Chris@537 145 break;
Chris@537 146
Chris@537 147 case FFTCache::Polar:
Chris@537 148 for (size_t y = 0; y < h; ++y) {
Chris@537 149 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 150 if (mag > factor) factor = mag;
Chris@537 151 ((float *)m_writebuf)[y * 2] = mag;
Chris@537 152 float phase = atan2f(imag[y], real[y]);
Chris@537 153 ((float *)m_writebuf)[y * 2 + 1] = phase;
Chris@537 154 }
Chris@537 155 break;
Chris@537 156 }
Chris@537 157
Chris@537 158 static float maxFactor = 0;
Chris@537 159 if (factor > maxFactor) maxFactor = factor;
Chris@537 160 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 161 std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
Chris@537 162 #endif
Chris@537 163
Chris@537 164 setNormalizationFactorToWritebuf(factor);
Chris@537 165
Chris@537 166 m_mfc->setColumnAt(x, m_writebuf);
Chris@537 167 }
Chris@537 168
Chris@537 169 size_t
Chris@537 170 FFTFileCacheWriter::getCacheSize(size_t width, size_t height,
Chris@537 171 FFTCache::StorageType type)
Chris@537 172 {
Chris@537 173 return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
Chris@537 174 (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
Chris@537 175 2 * sizeof(size_t); // matrix file header size
Chris@537 176 }
Chris@537 177
Chris@537 178 void
Chris@537 179 FFTFileCacheWriter::allColumnsWritten()
Chris@537 180 {
Chris@537 181 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 182 std::cerr << "FFTFileCacheWriter::allColumnsWritten" << std::endl;
Chris@537 183 #endif
Chris@537 184 m_mfc->close();
Chris@537 185 }
Chris@537 186