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
|