annotate data/fft/FFTFileCacheWriter.cpp @ 981:c6f2b93a7d52

Respond tidily to user cancellation during download, instead of going on to attempt to load the nonexistent file as a non-audio format
author Chris Cannam
date Tue, 09 Sep 2014 16:52:24 +0100
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