comparison data/fft/FFTFileCache.cpp @ 266:2268963dabd1

* FFT: fix invalid write of normalisation factor in compact mode of disc cache * FFT: fix range problem for normalisation factor in compact mode (it was stored as an unsigned scaled from an assumed float range of 0->1, which is not very plausible and not accurate enough even if true -- use a float instead) * Spectrogram: fix vertical zoom behaviour for log frequency spectrograms: make the thing in the middle of the display remain in the middle after zoom * Overview widget: don't update the detailed waveform if still decoding the audio file (too expensive to do all those redraws)
author Chris Cannam
date Fri, 08 Jun 2007 15:19:50 +0000
parents dc46851837d6
children 92e8dbde73cd
comparison
equal deleted inserted replaced
265:e08f486e8d8c 266:2268963dabd1
24 #include <QMutexLocker> 24 #include <QMutexLocker>
25 25
26 // The underlying matrix has height (m_height * 2 + 1). In each 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] 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 28 // etc, and then store the normalization factor (maximum magnitude) at
29 // [m_height * 2]. 29 // [m_height * 2]. In compact mode, the factor takes two cells.
30 30
31 FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode, 31 FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode,
32 StorageType storageType) : 32 StorageType storageType) :
33 m_writebuf(0), 33 m_writebuf(0),
34 m_readbuf(0), 34 m_readbuf(0),
36 m_readbufWidth(0), 36 m_readbufWidth(0),
37 m_mfc(new MatrixFile 37 m_mfc(new MatrixFile
38 (fileBase, mode, 38 (fileBase, mode,
39 storageType == Compact ? sizeof(uint16_t) : sizeof(float), 39 storageType == Compact ? sizeof(uint16_t) : sizeof(float),
40 mode == MatrixFile::ReadOnly)), 40 mode == MatrixFile::ReadOnly)),
41 m_storageType(storageType) 41 m_storageType(storageType),
42 m_factorSize(storageType == Compact ? 2 : 1)
42 { 43 {
43 // std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl; 44 // std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
44 } 45 }
45 46
46 FFTFileCache::~FFTFileCache() 47 FFTFileCache::~FFTFileCache()
58 59
59 size_t 60 size_t
60 FFTFileCache::getHeight() const 61 FFTFileCache::getHeight() const
61 { 62 {
62 size_t mh = m_mfc->getHeight(); 63 size_t mh = m_mfc->getHeight();
63 if (mh > 0) return (mh - 1) / 2; 64 if (mh > m_factorSize) return (mh - m_factorSize) / 2;
64 else return 0; 65 else return 0;
65 } 66 }
66 67
67 void 68 void
68 FFTFileCache::resize(size_t width, size_t height) 69 FFTFileCache::resize(size_t width, size_t height)
69 { 70 {
70 QMutexLocker locker(&m_writeMutex); 71 QMutexLocker locker(&m_writeMutex);
71 72
72 m_mfc->resize(width, height * 2 + 1); 73 m_mfc->resize(width, height * 2 + m_factorSize);
73 if (m_readbuf) { 74 if (m_readbuf) {
74 delete[] m_readbuf; 75 delete[] m_readbuf;
75 m_readbuf = 0; 76 m_readbuf = 0;
76 } 77 }
77 if (m_writebuf) { 78 if (m_writebuf) {
78 delete[] m_writebuf; 79 delete[] m_writebuf;
79 } 80 }
80 m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()]; 81 m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()];
81 } 82 }
82 83
83 void 84 void
84 FFTFileCache::reset() 85 FFTFileCache::reset()
85 { 86 {
227 ((float *)m_writebuf)[y * 2 + 1] = phases[y]; 228 ((float *)m_writebuf)[y * 2 + 1] = phases[y];
228 } 229 }
229 break; 230 break;
230 } 231 }
231 232
232 static float maxFactor = 0; 233 // static float maxFactor = 0;
233 if (factor > maxFactor) maxFactor = factor; 234 // if (factor > maxFactor) maxFactor = factor;
234 // std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl; 235 // std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
235 236
236 if (m_storageType == Compact) { 237 setNormalizationFactorToWritebuf(factor);
237 if (factor < 0.f || factor > 1.f) { 238
238 std::cerr << "WARNING: FFTFileCache::setColumnAt: Normalization factor " << factor << " out of range" << std::endl;
239 if (factor < 0.f) factor = 0.f;
240 if (factor > 1.f) factor = 1.f;
241 }
242 ((uint16_t *)m_writebuf)[h * 2] = (uint16_t)(factor * 65535.0);
243 } else {
244 ((float *)m_writebuf)[h * 2] = factor;
245 }
246 m_mfc->setColumnAt(x, m_writebuf); 239 m_mfc->setColumnAt(x, m_writebuf);
247 } 240 }
248 241
249 void 242 void
250 FFTFileCache::setColumnAt(size_t x, float *real, float *imag) 243 FFTFileCache::setColumnAt(size_t x, float *real, float *imag)
251 { 244 {
252 QMutexLocker locker(&m_writeMutex); 245 QMutexLocker locker(&m_writeMutex);
253 246
254 size_t h = getHeight(); 247 size_t h = getHeight();
255 248
256 float max = 0.0f; 249 float factor = 0.0f;
257 250
258 switch (m_storageType) { 251 switch (m_storageType) {
259 252
260 case Compact: 253 case Compact:
261 for (size_t y = 0; y < h; ++y) { 254 for (size_t y = 0; y < h; ++y) {
262 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); 255 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
263 if (mag > max) max = mag; 256 if (mag > factor) factor = mag;
264 } 257 }
265 for (size_t y = 0; y < h; ++y) { 258 for (size_t y = 0; y < h; ++y) {
266 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); 259 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
267 float phase = princargf(atan2f(imag[y], real[y])); 260 float phase = princargf(atan2f(imag[y], real[y]));
268 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0); 261 ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0);
269 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI)); 262 ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
270 } 263 }
271 break; 264 break;
272 265
273 case Rectangular: 266 case Rectangular:
274 for (size_t y = 0; y < h; ++y) { 267 for (size_t y = 0; y < h; ++y) {
275 ((float *)m_writebuf)[y * 2] = real[y]; 268 ((float *)m_writebuf)[y * 2] = real[y];
276 ((float *)m_writebuf)[y * 2 + 1] = imag[y]; 269 ((float *)m_writebuf)[y * 2 + 1] = imag[y];
277 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); 270 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
278 if (mag > max) max = mag; 271 if (mag > factor) factor = mag;
279 } 272 }
280 break; 273 break;
281 274
282 case Polar: 275 case Polar:
283 for (size_t y = 0; y < h; ++y) { 276 for (size_t y = 0; y < h; ++y) {
284 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); 277 float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
285 if (mag > max) max = mag; 278 if (mag > factor) factor = mag;
286 ((float *)m_writebuf)[y * 2] = mag; 279 ((float *)m_writebuf)[y * 2] = mag;
287 ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y])); 280 ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y]));
288 } 281 }
289 break; 282 break;
290 } 283 }
291 284
292 ((float *)m_writebuf)[h * 2] = max; 285 // static float maxFactor = 0;
286 // if (factor > maxFactor) maxFactor = factor;
287 // std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
288
289 setNormalizationFactorToWritebuf(factor);
290
293 m_mfc->setColumnAt(x, m_writebuf); 291 m_mfc->setColumnAt(x, m_writebuf);
294 } 292 }
295 293
296 size_t 294 size_t
297 FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type) 295 FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type)
298 { 296 {
299 return (height * 2 + 1) * width * 297 return (height * 2 + (type == Compact ? 2 : 1)) * width *
300 (type == Compact ? sizeof(uint16_t) : sizeof(float)) + 298 (type == Compact ? sizeof(uint16_t) : sizeof(float)) +
301 2 * sizeof(size_t); // matrix file header size 299 2 * sizeof(size_t); // matrix file header size
302 } 300 }
303 301
304 void 302 void