annotate data/fft/FFTFileCacheWriter.cpp @ 561:863ad4b1f841

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