//============================================================================== bool AudioThumbnail::setDataSource (LevelDataSource* newSource) { jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); numSamplesFinished = 0; if (cache.loadThumb (*this, newSource->hashCode) && isFullyLoaded()) { source = newSource; // (make sure this isn't done before loadThumb is called) source->lengthInSamples = totalSamples; source->sampleRate = sampleRate; source->numChannels = (unsigned int) numChannels; source->numSamplesFinished = numSamplesFinished; } else { source = newSource; // (make sure this isn't done before loadThumb is called) const ScopedLock sl (lock); source->initialise (numSamplesFinished); totalSamples = source->lengthInSamples; sampleRate = source->sampleRate; numChannels = (int32) source->numChannels; createChannels (1 + (int) (totalSamples / samplesPerThumbSample)); } return sampleRate > 0 && totalSamples > 0; }
int useTimeSlice() { if (isFullyLoaded()) { if (reader != nullptr && source != nullptr) releaseResources(); return -1; } bool justFinished = false; { const ScopedLock sl (readerLock); createReader(); if (reader != nullptr) { if (! readNextBlock()) return 0; justFinished = true; } } if (justFinished) owner.cache.storeThumb (owner, hashCode); return timeBeforeDeletingReader; }
bool readNextBlock() { jassert (reader != nullptr); if (! isFullyLoaded()) { const int numToDo = (int) jmin (256 * (int64) owner.samplesPerThumbSample, lengthInSamples - numSamplesFinished); if (numToDo > 0) { int64 startSample = numSamplesFinished; const int firstThumbIndex = sampleToThumbSample (startSample); const int lastThumbIndex = sampleToThumbSample (startSample + numToDo); const int numThumbSamps = lastThumbIndex - firstThumbIndex; HeapBlock<MinMaxValue> levelData ((size_t) numThumbSamps * numChannels); HeapBlock<MinMaxValue*> levels (numChannels); for (int i = 0; i < (int) numChannels; ++i) levels[i] = levelData + i * numThumbSamps; HeapBlock<Range<float> > levelsRead (numChannels); for (int i = 0; i < numThumbSamps; ++i) { reader->readMaxLevels ((firstThumbIndex + i) * owner.samplesPerThumbSample, owner.samplesPerThumbSample, levelsRead, (int) numChannels); for (int j = 0; j < (int) numChannels; ++j) levels[j][i].setFloat (levelsRead[j]); } { const ScopedUnlock su (readerLock); owner.setLevels (levels, firstThumbIndex, (int) numChannels, numThumbSamps); } numSamplesFinished += numToDo; lastReaderUseTime = Time::getMillisecondCounter(); } } return isFullyLoaded(); }
bool readNextBlock() { jassert (reader != nullptr); if (! isFullyLoaded()) { const int numToDo = (int) jmin (256 * (int64) owner.samplesPerThumbSample, lengthInSamples - numSamplesFinished); if (numToDo > 0) { int64 startSample = numSamplesFinished; const int firstThumbIndex = sampleToThumbSample (startSample); const int lastThumbIndex = sampleToThumbSample (startSample + numToDo); const int numThumbSamps = lastThumbIndex - firstThumbIndex; HeapBlock<MinMaxValue> levelData ((size_t) numThumbSamps * 2); MinMaxValue* levels[2] = { levelData, levelData + numThumbSamps }; for (int i = 0; i < numThumbSamps; ++i) { float lowestLeft, highestLeft, lowestRight, highestRight; reader->readMaxLevels ((firstThumbIndex + i) * owner.samplesPerThumbSample, owner.samplesPerThumbSample, lowestLeft, highestLeft, lowestRight, highestRight); levels[0][i].setFloat (lowestLeft, highestLeft); levels[1][i].setFloat (lowestRight, highestRight); } { const ScopedUnlock su (readerLock); owner.setLevels (levels, firstThumbIndex, 2, numThumbSamps); } numSamplesFinished += numToDo; lastReaderUseTime = Time::getMillisecondCounter(); } } return isFullyLoaded(); }
void initialise (int64 samplesFinished) { const ScopedLock sl (readerLock); numSamplesFinished = samplesFinished; createReader(); if (reader != nullptr) { lengthInSamples = reader->lengthInSamples; numChannels = reader->numChannels; sampleRate = reader->sampleRate; if (lengthInSamples <= 0 || isFullyLoaded()) reader = nullptr; else owner.cache.getTimeSliceThread().addTimeSliceClient (this); } }
int useTimeSlice() override { if (isFullyLoaded()) { if (reader != nullptr && source != nullptr) { if (Time::getMillisecondCounter() > lastReaderUseTime + timeBeforeDeletingReader) releaseResources(); else return 200; } return -1; } bool justFinished = false; { const ScopedLock sl (readerLock); createReader(); if (reader != nullptr) { if (! readNextBlock()) return 0; justFinished = true; } } if (justFinished) owner.cache.storeThumb (owner, hashCode); return 200; }