annotate data/fft/FFTFileCacheWriter.cpp @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 59e7fe1b1003
children cc27f35aa75c
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@929 36 int width, int 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@843 47 cerr << "FFTFileCacheWriter: storage type is " << (storageType == FFTCache::Compact ? "Compact" : storageType == FFTCache::Polar ? "Polar" : "Rectangular") << ", size " << width << "x" << height << 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@929 65 int
Chris@537 66 FFTFileCacheWriter::getWidth() const
Chris@537 67 {
Chris@537 68 return m_mfc->getWidth();
Chris@537 69 }
Chris@537 70
Chris@929 71 int
Chris@537 72 FFTFileCacheWriter::getHeight() const
Chris@537 73 {
Chris@929 74 int 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@929 80 FFTFileCacheWriter::haveSetColumnAt(int x) const
Chris@550 81 {
Chris@550 82 return m_mfc->haveSetColumnAt(x);
Chris@550 83 }
Chris@550 84
Chris@537 85 void
Chris@929 86 FFTFileCacheWriter::setColumnAt(int x, float *mags, float *phases, float factor)
Chris@537 87 {
Chris@929 88 int h = getHeight();
Chris@537 89
Chris@537 90 switch (m_storageType) {
Chris@537 91
Chris@537 92 case FFTCache::Compact:
Chris@929 93 for (int 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@929 100 for (int 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@929 107 for (int 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@843 117 cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << 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@929 126 FFTFileCacheWriter::setColumnAt(int x, float *real, float *imag)
Chris@537 127 {
Chris@929 128 int 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@929 135 for (int 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@929 139 for (int 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@929 148 for (int 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@929 157 for (int 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@843 170 cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << 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@929 178 int
Chris@929 179 FFTFileCacheWriter::getCacheSize(int width, int 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@929 184 2 * sizeof(int); // 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@690 191 SVDEBUG << "FFTFileCacheWriter::allColumnsWritten" << endl;
Chris@537 192 #endif
Chris@537 193 m_mfc->close();
Chris@537 194 }
Chris@537 195