Mercurial > hg > svcore
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 |