annotate data/fft/FFTFileCacheWriter.cpp @ 548:1469caaa8e67

* Finer locking in fft caches; fix displayed bin ranges in spectrogram
author Chris Cannam
date Thu, 05 Feb 2009 12:05:28 +0000
parents 3cc4b7cd2aa5
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