comparison data/fft/FFTFileCache.cpp @ 148:1a42221a1522

* Reorganising code base. This revision will not compile.
author Chris Cannam
date Mon, 31 Jul 2006 11:49:58 +0000
parents
children 4b2ea82fd0ed
comparison
equal deleted inserted replaced
147:3a13b0d4934e 148:1a42221a1522
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "FFTFileCache.h"
17
18 #include "MatrixFile.h"
19
20 #include "base/Profiler.h"
21
22 #include <iostream>
23
24 #include <QMutexLocker>
25
26 // The underlying matrix has height (m_height * 2 + 1). In each
27 // column we store magnitude at [0], [2] etc and phase at [1], [3]
28 // etc, and then store the normalization factor (maximum magnitude) at
29 // [m_height * 2].
30
31 FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode,
32 StorageType storageType) :
33 m_writebuf(0),
34 m_readbuf(0),
35 m_readbufCol(0),
36 m_readbufWidth(0),
37 m_mfc(new MatrixFile
38 (fileBase, mode,
39 storageType == Compact ? sizeof(uint16_t) : sizeof(float),
40 mode == MatrixFile::ReadOnly)),
41 m_storageType(storageType)
42 {
43 std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
44 }
45
46 FFTFileCache::~FFTFileCache()
47 {
48 if (m_readbuf) delete[] m_readbuf;
49 if (m_writebuf) delete[] m_writebuf;
50 delete m_mfc;
51 }
52
53 size_t
54 FFTFileCache::getWidth() const
55 {
56 return m_mfc->getWidth();
57 }
58
59 size_t
60 FFTFileCache::getHeight() const
61 {
62 size_t mh = m_mfc->getHeight();
63 if (mh > 0) return (mh - 1) / 2;
64 else return 0;
65 }
66
67 void
68 FFTFileCache::resize(size_t width, size_t height)
69 {
70 QMutexLocker locker(&m_writeMutex);
71
72 m_mfc->resize(width, height * 2 + 1);
73 if (m_readbuf) {
74 delete[] m_readbuf;
75 m_readbuf = 0;
76 }
77 if (m_writebuf) {
78 delete[] m_writebuf;
79 }
80 m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()];
81 }
82
83 void
84 FFTFileCache::reset()
85 {
86 m_mfc->reset();
87 }
88
89 float
90 FFTFileCache::getMagnitudeAt(size_t x, size_t y) const
91 {
92 float value = 0.f;
93
94 switch (m_storageType) {
95
96 case Compact:
97 value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
98 * getNormalizationFactor(x);
99 break;
100
101 case Rectangular:
102 {
103 float real, imag;
104 getValuesAt(x, y, real, imag);
105 value = sqrtf(real * real + imag * imag);
106 break;
107 }
108
109 case Polar:
110 value = getFromReadBufStandard(x, y * 2);
111 break;
112 }
113
114 return value;
115 }
116
117 float
118 FFTFileCache::getNormalizedMagnitudeAt(size_t x, size_t y) const
119 {
120 float value = 0.f;
121
122 switch (m_storageType) {
123
124 case Compact:
125 value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
126 break;
127
128 default:
129 {
130 float mag = getMagnitudeAt(x, y);
131 float factor = getNormalizationFactor(x);
132 if (factor != 0) value = mag / factor;
133 else value = 0.f;
134 break;
135 }
136 }
137
138 return value;
139 }
140
141 float
142 FFTFileCache::getMaximumMagnitudeAt(size_t x) const
143 {
144 return getNormalizationFactor(x);
145 }
146
147 float
148 FFTFileCache::getPhaseAt(size_t x, size_t y) const
149 {
150 float value = 0.f;
151
152 switch (m_storageType) {
153
154 case Compact:
155 value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
156 break;
157
158 case Rectangular:
159 {
160 float real, imag;
161 getValuesAt(x, y, real, imag);
162 value = princargf(atan2f(imag, real));
163 break;
164 }
165
166 case Polar:
167 value = getFromReadBufStandard(x, y * 2 + 1);
168 break;
169 }
170
171 return value;
172 }
173
174 void
175 FFTFileCache::getValuesAt(size_t x, size_t y, float &real, float &imag) const
176 {
177 switch (m_storageType) {
178
179 case Rectangular:
180 real = getFromReadBufStandard(x, y * 2);
181 imag = getFromReadBufStandard(x, y * 2 + 1);
182 return;
183
184 default:
185 float mag = getMagnitudeAt(x, y);
186 float phase = getPhaseAt(x, y);
187 real = mag * cosf(phase);
188 imag = mag * sinf(phase);
189 return;
190 }
191 }
192
193 bool
194 FFTFileCache::haveSetColumnAt(size_t x) const
195 {
196 return m_mfc->haveSetColumnAt(x);
197 }
198
199 void
200 FFTFileCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
201 {
202 QMutexLocker locker(&m_writeMutex);
203
204 size_t h = getHeight();
205
206 switch (m_storageType) {
207
208 case Compact:
209 for (size_t y = 0; y < h; ++y) {
210 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
211 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
212 }
213 break;
214
215 case Rectangular:
216 for (size_t y = 0; y < h; ++y) {
217 ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
218 ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
219 }
220 break;
221
222 case Polar:
223 for (size_t y = 0; y < h; ++y) {
224 ((float *)m_writebuf)[y * 2] = mags[y];
225 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
226 }
227 break;
228 }
229
230 static float maxFactor = 0;
231 if (factor > maxFactor) maxFactor = factor;
232 // std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
233
234 if (m_storageType == Compact) {
235 ((uint16_t *)m_writebuf)[h * 2] = factor * 65535.0;
236 } else {
237 ((float *)m_writebuf)[h * 2] = factor;
238 }
239 m_mfc->setColumnAt(x, m_writebuf);
240 }
241
242 void
243 FFTFileCache::setColumnAt(size_t x, float *real, float *imag)
244 {
245 QMutexLocker locker(&m_writeMutex);
246
247 size_t h = getHeight();
248
249 float max = 0.0f;
250
251 switch (m_storageType) {
252
253 case Compact:
254 for (size_t y = 0; y < h; ++y) {
255 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
256 if (mag > max) max = mag;
257 }
258 for (size_t y = 0; y < h; ++y) {
259 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
260 float phase = princargf(atan2f(imag[y], real[y]));
261 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0);
262 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
263 }
264 break;
265
266 case Rectangular:
267 for (size_t y = 0; y < h; ++y) {
268 ((float *)m_writebuf)[y * 2] = real[y];
269 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
270 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
271 if (mag > max) max = mag;
272 }
273 break;
274
275 case Polar:
276 for (size_t y = 0; y < h; ++y) {
277 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
278 if (mag > max) max = mag;
279 ((float *)m_writebuf)[y * 2] = mag;
280 ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y]));
281 }
282 break;
283 }
284
285 ((float *)m_writebuf)[h * 2] = max;
286 m_mfc->setColumnAt(x, m_writebuf);
287 }
288