# HG changeset patch # User Chris Cannam # Date 1181315990 0 # Node ID 2268963dabd103c87156f36b15558ad0a90f252c # Parent e08f486e8d8ca459bf40064da32360eca34bd61d * 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) diff -r e08f486e8d8c -r 2268963dabd1 base/LogRange.cpp --- a/base/LogRange.cpp Wed Jun 06 16:24:55 2007 +0000 +++ b/base/LogRange.cpp Fri Jun 08 15:19:50 2007 +0000 @@ -58,3 +58,8 @@ return log10f(fabsf(value)); } +float +LogRange::unmap(float value) +{ + return powf(10.0, value); +} diff -r e08f486e8d8c -r 2268963dabd1 base/LogRange.h --- a/base/LogRange.h Wed Jun 06 16:24:55 2007 +0000 +++ b/base/LogRange.h Fri Jun 08 15:19:50 2007 +0000 @@ -33,6 +33,12 @@ * value if the absolute value is zero. */ static float map(float value, float thresh = -10); + + /** + * Map a value from the logarithmic range back again. This just + * means taking the value'th power of ten. + */ + static float unmap(float value); }; #endif diff -r e08f486e8d8c -r 2268963dabd1 data/fft/FFTFileCache.cpp --- a/data/fft/FFTFileCache.cpp Wed Jun 06 16:24:55 2007 +0000 +++ b/data/fft/FFTFileCache.cpp Fri Jun 08 15:19:50 2007 +0000 @@ -26,7 +26,7 @@ // The underlying matrix has height (m_height * 2 + 1). In each // column we store magnitude at [0], [2] etc and phase at [1], [3] // etc, and then store the normalization factor (maximum magnitude) at -// [m_height * 2]. +// [m_height * 2]. In compact mode, the factor takes two cells. FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode, StorageType storageType) : @@ -38,7 +38,8 @@ (fileBase, mode, storageType == Compact ? sizeof(uint16_t) : sizeof(float), mode == MatrixFile::ReadOnly)), - m_storageType(storageType) + m_storageType(storageType), + m_factorSize(storageType == Compact ? 2 : 1) { // std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl; } @@ -60,7 +61,7 @@ FFTFileCache::getHeight() const { size_t mh = m_mfc->getHeight(); - if (mh > 0) return (mh - 1) / 2; + if (mh > m_factorSize) return (mh - m_factorSize) / 2; else return 0; } @@ -69,7 +70,7 @@ { QMutexLocker locker(&m_writeMutex); - m_mfc->resize(width, height * 2 + 1); + m_mfc->resize(width, height * 2 + m_factorSize); if (m_readbuf) { delete[] m_readbuf; m_readbuf = 0; @@ -77,7 +78,7 @@ if (m_writebuf) { delete[] m_writebuf; } - m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()]; + m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()]; } void @@ -229,20 +230,12 @@ break; } - static float maxFactor = 0; - if (factor > maxFactor) maxFactor = factor; -// std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl; +// static float maxFactor = 0; +// if (factor > maxFactor) maxFactor = factor; +// std::cerr << "Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl; - if (m_storageType == Compact) { - if (factor < 0.f || factor > 1.f) { - std::cerr << "WARNING: FFTFileCache::setColumnAt: Normalization factor " << factor << " out of range" << std::endl; - if (factor < 0.f) factor = 0.f; - if (factor > 1.f) factor = 1.f; - } - ((uint16_t *)m_writebuf)[h * 2] = (uint16_t)(factor * 65535.0); - } else { - ((float *)m_writebuf)[h * 2] = factor; - } + setNormalizationFactorToWritebuf(factor); + m_mfc->setColumnAt(x, m_writebuf); } @@ -253,19 +246,19 @@ size_t h = getHeight(); - float max = 0.0f; + float factor = 0.0f; switch (m_storageType) { case Compact: for (size_t y = 0; y < h; ++y) { float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); - if (mag > max) max = mag; + if (mag > factor) factor = mag; } for (size_t y = 0; y < h; ++y) { float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); float phase = princargf(atan2f(imag[y], real[y])); - ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0); + ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / factor) * 65535.0); ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI)); } break; @@ -275,28 +268,33 @@ ((float *)m_writebuf)[y * 2] = real[y]; ((float *)m_writebuf)[y * 2 + 1] = imag[y]; float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); - if (mag > max) max = mag; + if (mag > factor) factor = mag; } break; case Polar: for (size_t y = 0; y < h; ++y) { float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]); - if (mag > max) max = mag; + if (mag > factor) factor = mag; ((float *)m_writebuf)[y * 2] = mag; ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y])); } break; } - ((float *)m_writebuf)[h * 2] = max; +// static float maxFactor = 0; +// if (factor > maxFactor) maxFactor = factor; +// std::cerr << "[RI] Column " << x << ": normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl; + + setNormalizationFactorToWritebuf(factor); + m_mfc->setColumnAt(x, m_writebuf); } size_t FFTFileCache::getCacheSize(size_t width, size_t height, StorageType type) { - return (height * 2 + 1) * width * + return (height * 2 + (type == Compact ? 2 : 1)) * width * (type == Compact ? sizeof(uint16_t) : sizeof(float)) + 2 * sizeof(size_t); // matrix file header size } diff -r e08f486e8d8c -r 2268963dabd1 data/fft/FFTFileCache.h --- a/data/fft/FFTFileCache.h Wed Jun 06 16:24:55 2007 +0000 +++ b/data/fft/FFTFileCache.h Fri Jun 08 15:19:50 2007 +0000 @@ -97,18 +97,47 @@ void populateReadBuf(size_t x) const; float getNormalizationFactor(size_t col) const { + size_t h = m_mfc->getHeight(); + if (h < m_factorSize) return 0; if (m_storageType != Compact) { - return getFromReadBufStandard(col, m_mfc->getHeight() - 1); + return getFromReadBufStandard(col, h - 1); } else { - float factor; - factor = getFromReadBufCompactUnsigned(col, m_mfc->getHeight() - 1); - return factor / 65535.0; + union { + float f; + uint16_t u[2]; + } factor; + if (!m_readbuf || + !(m_readbufCol == col || + (m_readbufWidth > 1 && m_readbufCol+1 == col))) { + populateReadBuf(col); + } + size_t ix = (col - m_readbufCol) * m_mfc->getHeight() + h; + factor.u[0] = ((uint16_t *)m_readbuf)[ix - 2]; + factor.u[1] = ((uint16_t *)m_readbuf)[ix - 1]; + return factor.f; } } + void setNormalizationFactorToWritebuf(float newfactor) { + size_t h = m_mfc->getHeight(); + if (h < m_factorSize) return; + if (m_storageType != Compact) { + ((float *)m_writebuf)[h - 1] = newfactor; + } else { + union { + float f; + uint16_t u[2]; + } factor; + factor.f = newfactor; + ((uint16_t *)m_writebuf)[h - 2] = factor.u[0]; + ((uint16_t *)m_writebuf)[h - 1] = factor.u[1]; + } + } + MatrixFile *m_mfc; QMutex m_writeMutex; StorageType m_storageType; + size_t m_factorSize; }; #endif diff -r e08f486e8d8c -r 2268963dabd1 data/fileio/CodedAudioFileReader.cpp --- a/data/fileio/CodedAudioFileReader.cpp Wed Jun 06 16:24:55 2007 +0000 +++ b/data/fileio/CodedAudioFileReader.cpp Fri Jun 08 15:19:50 2007 +0000 @@ -129,11 +129,11 @@ m_cacheWriteBufferSize); m_cacheWriteBufferIndex = 0; + } - if (m_cacheWriteBufferIndex % 10240 == 0 && - m_cacheFileReader) { - m_cacheFileReader->updateFrameCount(); - } + if (m_cacheWriteBufferIndex % 10240 == 0 && + m_cacheFileReader) { + m_cacheFileReader->updateFrameCount(); } break; diff -r e08f486e8d8c -r 2268963dabd1 data/model/WaveFileModel.cpp --- a/data/model/WaveFileModel.cpp Wed Jun 06 16:24:55 2007 +0000 +++ b/data/model/WaveFileModel.cpp Fri Jun 08 15:19:50 2007 +0000 @@ -96,14 +96,22 @@ { bool ready = (isOK() && (m_fillThread == 0)); double c = double(m_lastFillExtent) / double(getEndFrame() - getStartFrame()); + static int prevCompletion = 0; if (completion) { *completion = int(c * 100.0 + 0.01); if (m_reader) { int decodeCompletion = m_reader->getDecodeCompletion(); -// std::cerr << "decodeCompletion " << decodeCompletion << ", completion " << *completion << std::endl; -// if (decodeCompletion < *completion) *completion = decodeCompletion; - if (decodeCompletion < 100) *completion = decodeCompletion; + if (decodeCompletion < 90) *completion = decodeCompletion; + else *completion = std::min(*completion, decodeCompletion); } + if (*completion != 0 && + *completion != 100 && + prevCompletion != 0 && + prevCompletion > *completion) { + // just to avoid completion going backwards + *completion = prevCompletion; + } + prevCompletion = *completion; } #ifdef DEBUG_WAVE_FILE_MODEL std::cerr << "WaveFileModel::isReady(): ready = " << ready << ", completion = " << (completion ? *completion : -1) << std::endl;