Mercurial > hg > svcore
diff data/model/WaveFileModel.cpp @ 383:94fc0591ea43 1.2-stable
* merge from trunk (1.2 ended up being tracked from trunk, but we may want
this branch for fixes later)
author | Chris Cannam |
---|---|
date | Wed, 27 Feb 2008 10:32:45 +0000 |
parents | 700cd3350391 |
children |
line wrap: on
line diff
--- a/data/model/WaveFileModel.cpp Fri Nov 30 17:36:14 2007 +0000 +++ b/data/model/WaveFileModel.cpp Wed Feb 27 10:32:45 2008 +0000 @@ -189,7 +189,7 @@ // This is used for e.g. audio playback. // Could be much more efficient (although compiler optimisation will help) - if (start > m_startFrame) { + if (start >= m_startFrame) { start -= m_startFrame; } else { for (size_t i = 0; i < count; ++i) buffer[i] = 0.f; @@ -211,12 +211,14 @@ // << start << ", " << end << "): calling reader" << std::endl; #endif - SampleBlock frames; + int channels = getChannelCount(); + + SampleBlock frames(count * channels); m_reader->getInterleavedFrames(start, count, frames); size_t i = 0; - int ch0 = channel, ch1 = channel, channels = getChannelCount(); + int ch0 = channel, ch1 = channel; if (channel == -1) { ch0 = 0; ch1 = channels - 1; @@ -262,12 +264,14 @@ return 0; } - SampleBlock frames; + int channels = getChannelCount(); + + SampleBlock frames(count * channels); m_reader->getInterleavedFrames(start, count, frames); size_t i = 0; - int ch0 = channel, ch1 = channel, channels = getChannelCount(); + int ch0 = channel, ch1 = channel; if (channel == -1) { ch0 = 0; ch1 = channels - 1; @@ -292,12 +296,112 @@ return i; } +size_t +WaveFileModel::getData(size_t fromchannel, size_t tochannel, + size_t start, size_t count, + float **buffer) const +{ + size_t channels = getChannelCount(); + + if (fromchannel > tochannel) { + std::cerr << "ERROR: WaveFileModel::getData: fromchannel (" + << fromchannel << ") > tochannel (" << tochannel << ")" + << std::endl; + return 0; + } + + if (tochannel >= channels) { + std::cerr << "ERROR: WaveFileModel::getData: tochannel (" + << tochannel << ") >= channel count (" << channels << ")" + << std::endl; + return 0; + } + + if (fromchannel == tochannel) { + return getData(fromchannel, start, count, buffer[0]); + } + + size_t reqchannels = (tochannel - fromchannel) + 1; + + // Always read these directly from the file. + // This is used for e.g. audio playback. + // Could be much more efficient (although compiler optimisation will help) + + if (start >= m_startFrame) { + start -= m_startFrame; + } else { + for (size_t c = 0; c < reqchannels; ++c) { + for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f; + } + if (count <= m_startFrame - start) { + return 0; + } else { + count -= (m_startFrame - start); + start = 0; + } + } + + if (!m_reader || !m_reader->isOK() || count == 0) { + for (size_t c = 0; c < reqchannels; ++c) { + for (size_t i = 0; i < count; ++i) buffer[c][i] = 0.f; + } + return 0; + } + + SampleBlock frames(count * channels); + m_reader->getInterleavedFrames(start, count, frames); + + size_t i = 0; + + int ch0 = fromchannel, ch1 = tochannel; + + size_t index = 0, available = frames.size(); + + while (i < count) { + + if (index >= available) break; + + size_t destc = 0; + + for (size_t c = 0; c < channels; ++c) { + + if (c >= fromchannel && c <= tochannel) { + buffer[destc][i] = frames[index]; + ++destc; + } + + ++index; + } + + ++i; + } + + return i; +} + +size_t +WaveFileModel::getSummaryBlockSize(size_t desired) const +{ + int cacheType = 0; + int power = m_zoomConstraint.getMinCachePower(); + size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize + (desired, cacheType, power, ZoomConstraint::RoundDown); + if (cacheType != 0 && cacheType != 1) { + // We will be reading directly from file, so can satisfy any + // blocksize requirement + return desired; + } else { + return roundedBlockSize; + } +} + void WaveFileModel::getSummaries(size_t channel, size_t start, size_t count, RangeBlock &ranges, size_t &blockSize) const { ranges.clear(); if (!isOK()) return; + ranges.reserve((count / blockSize) + 1); if (start > m_startFrame) start -= m_startFrame; else if (count <= m_startFrame - start) return; @@ -308,8 +412,8 @@ int cacheType = 0; int power = m_zoomConstraint.getMinCachePower(); - blockSize = m_zoomConstraint.getNearestBlockSize - (blockSize, cacheType, power, ZoomConstraint::RoundUp); + size_t roundedBlockSize = m_zoomConstraint.getNearestBlockSize + (blockSize, cacheType, power, ZoomConstraint::RoundDown); size_t channels = getChannelCount(); @@ -323,17 +427,26 @@ // matter by putting a single cache in getInterleavedFrames // for short queries. - SampleBlock frames; - m_reader->getInterleavedFrames(start, count, frames); + m_directReadMutex.lock(); + + if (m_lastDirectReadStart != start || + m_lastDirectReadCount != count || + m_directRead.empty()) { + + m_reader->getInterleavedFrames(start, count, m_directRead); + m_lastDirectReadStart = start; + m_lastDirectReadCount = count; + } + float max = 0.0, min = 0.0, total = 0.0; size_t i = 0, got = 0; while (i < count) { size_t index = i * channels + channel; - if (index >= frames.size()) break; + if (index >= m_directRead.size()) break; - float sample = frames[index]; + float sample = m_directRead[index]; if (sample > max || got == 0) max = sample; if (sample < min || got == 0) min = sample; total += fabsf(sample); @@ -348,6 +461,8 @@ } } + m_directReadMutex.unlock(); + if (got > 0) { ranges.push_back(Range(min, max, total / got)); } @@ -360,6 +475,8 @@ const RangeBlock &cache = m_cache[cacheType]; + blockSize = roundedBlockSize; + size_t cacheBlock, div; if (cacheType == 0) {