annotate data/fft/FFTFileCacheWriter.cpp @ 588:d04b8674b710

* Try to identify the properly conformant audio file structure written out by Sonic Annotator (but we still don't actually import it yet)
author Chris Cannam
date Wed, 13 May 2009 13:30:08 +0000
parents f9cf4b49b08b
children 06f13a3b9e9e
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@577 46 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 47 std::cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << std::endl;
Chris@577 48 #endif
Chris@550 49 m_mfc->setAutoClose(true);
Chris@537 50 m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
Chris@537 51 }
Chris@537 52
Chris@537 53 FFTFileCacheWriter::~FFTFileCacheWriter()
Chris@537 54 {
Chris@537 55 if (m_writebuf) delete[] m_writebuf;
Chris@537 56 delete m_mfc;
Chris@537 57 }
Chris@537 58
Chris@537 59 QString
Chris@537 60 FFTFileCacheWriter::getFileBase() const
Chris@537 61 {
Chris@537 62 return m_fileBase;
Chris@537 63 }
Chris@537 64
Chris@537 65 size_t
Chris@537 66 FFTFileCacheWriter::getWidth() const
Chris@537 67 {
Chris@537 68 return m_mfc->getWidth();
Chris@537 69 }
Chris@537 70
Chris@537 71 size_t
Chris@537 72 FFTFileCacheWriter::getHeight() const
Chris@537 73 {
Chris@537 74 size_t mh = m_mfc->getHeight();
Chris@537 75 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
Chris@537 76 else return 0;
Chris@537 77 }
Chris@537 78
Chris@550 79 bool
Chris@550 80 FFTFileCacheWriter::haveSetColumnAt(size_t x) const
Chris@550 81 {
Chris@550 82 return m_mfc->haveSetColumnAt(x);
Chris@550 83 }
Chris@550 84
Chris@537 85 void
Chris@537 86 FFTFileCacheWriter::setColumnAt(size_t x, float *mags, float *phases, float factor)
Chris@537 87 {
Chris@537 88 size_t h = getHeight();
Chris@537 89
Chris@537 90 switch (m_storageType) {
Chris@537 91
Chris@537 92 case FFTCache::Compact:
Chris@537 93 for (size_t y = 0; y < h; ++y) {
Chris@537 94 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
Chris@537 95 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
Chris@537 96 }
Chris@537 97 break;
Chris@537 98
Chris@537 99 case FFTCache::Rectangular:
Chris@537 100 for (size_t y = 0; y < h; ++y) {
Chris@537 101 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
Chris@537 102 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
Chris@537 103 }
Chris@537 104 break;
Chris@537 105
Chris@537 106 case FFTCache::Polar:
Chris@537 107 for (size_t y = 0; y < h; ++y) {
Chris@537 108 ((float *)m_writebuf)[y * 2] = mags[y];
Chris@537 109 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
Chris@537 110 }
Chris@537 111 break;
Chris@537 112 }
Chris@537 113
Chris@537 114 static float maxFactor = 0;
Chris@537 115 if (factor > maxFactor) maxFactor = factor;
Chris@537 116 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 117 std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
Chris@537 118 #endif
Chris@537 119
Chris@537 120 setNormalizationFactorToWritebuf(factor);
Chris@537 121
Chris@537 122 m_mfc->setColumnAt(x, m_writebuf);
Chris@537 123 }
Chris@537 124
Chris@537 125 void
Chris@537 126 FFTFileCacheWriter::setColumnAt(size_t x, float *real, float *imag)
Chris@537 127 {
Chris@537 128 size_t h = getHeight();
Chris@537 129
Chris@537 130 float factor = 0.0f;
Chris@537 131
Chris@537 132 switch (m_storageType) {
Chris@537 133
Chris@537 134 case FFTCache::Compact:
Chris@537 135 for (size_t y = 0; y < h; ++y) {
Chris@537 136 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 137 if (mag > factor) factor = mag;
Chris@537 138 }
Chris@537 139 for (size_t y = 0; y < h; ++y) {
Chris@537 140 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 141 float phase = atan2f(imag[y], real[y]);
Chris@537 142 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
Chris@537 143 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@537 144 }
Chris@537 145 break;
Chris@537 146
Chris@537 147 case FFTCache::Rectangular:
Chris@537 148 for (size_t y = 0; y < h; ++y) {
Chris@537 149 ((float *)m_writebuf)[y * 2] = real[y];
Chris@537 150 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
Chris@537 151 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 152 if (mag > factor) factor = mag;
Chris@537 153 }
Chris@537 154 break;
Chris@537 155
Chris@537 156 case FFTCache::Polar:
Chris@537 157 for (size_t y = 0; y < h; ++y) {
Chris@537 158 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
Chris@537 159 if (mag > factor) factor = mag;
Chris@537 160 ((float *)m_writebuf)[y * 2] = mag;
Chris@537 161 float phase = atan2f(imag[y], real[y]);
Chris@537 162 ((float *)m_writebuf)[y * 2 + 1] = phase;
Chris@537 163 }
Chris@537 164 break;
Chris@537 165 }
Chris@537 166
Chris@537 167 static float maxFactor = 0;
Chris@537 168 if (factor > maxFactor) maxFactor = factor;
Chris@537 169 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 170 std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
Chris@537 171 #endif
Chris@537 172
Chris@537 173 setNormalizationFactorToWritebuf(factor);
Chris@537 174
Chris@537 175 m_mfc->setColumnAt(x, m_writebuf);
Chris@537 176 }
Chris@537 177
Chris@537 178 size_t
Chris@537 179 FFTFileCacheWriter::getCacheSize(size_t width, size_t height,
Chris@537 180 FFTCache::StorageType type)
Chris@537 181 {
Chris@537 182 return (height * 2 + (type == FFTCache::Compact ? 2 : 1)) * width *
Chris@537 183 (type == FFTCache::Compact ? sizeof(uint16_t) : sizeof(float)) +
Chris@537 184 2 * sizeof(size_t); // matrix file header size
Chris@537 185 }
Chris@537 186
Chris@537 187 void
Chris@537 188 FFTFileCacheWriter::allColumnsWritten()
Chris@537 189 {
Chris@537 190 #ifdef DEBUG_FFT_FILE_CACHE_WRITER
Chris@537 191 std::cerr << "FFTFileCacheWriter::allColumnsWritten" << std::endl;
Chris@537 192 #endif
Chris@537 193 m_mfc->close();
Chris@537 194 }
Chris@537 195