diff --git a/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp b/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp index f3008bac44..ac1a756562 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp +++ b/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp @@ -115,7 +115,7 @@ bool AudioFormatReader::read (int* const* destChannels, return true; } -static void readChannels (AudioFormatReader& reader, int** chans, AudioBuffer* buffer, +static bool readChannels (AudioFormatReader& reader, int** chans, AudioBuffer* buffer, int startSample, int numSamples, int64 readerStartSample, int numTargetChannels, bool convertToFloat) { @@ -123,13 +123,16 @@ static void readChannels (AudioFormatReader& reader, int** chans, AudioBuffer (buffer->getWritePointer (j, startSample)); chans[numTargetChannels] = nullptr; - reader.read (chans, numTargetChannels, readerStartSample, numSamples, true); + + const bool success = reader.read (chans, numTargetChannels, readerStartSample, numSamples, true); if (convertToFloat) convertFixedToFloat (chans, numTargetChannels, numSamples); + + return success; } -void AudioFormatReader::read (AudioBuffer* buffer, +bool AudioFormatReader::read (AudioBuffer* buffer, int startSample, int numSamples, int64 readerStartSample, @@ -139,58 +142,61 @@ void AudioFormatReader::read (AudioBuffer* buffer, jassert (buffer != nullptr); jassert (startSample >= 0 && startSample + numSamples <= buffer->getNumSamples()); - if (numSamples > 0) - { - auto numTargetChannels = buffer->getNumChannels(); - - if (numTargetChannels <= 2) - { - int* dests[2] = { reinterpret_cast (buffer->getWritePointer (0, startSample)), - reinterpret_cast (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr) }; - int* chans[3] = {}; - - if (useReaderLeftChan == useReaderRightChan) - { - chans[0] = dests[0]; + if (numSamples <= 0) + return true; - if (numChannels > 1) - chans[1] = dests[1]; - } - else if (useReaderLeftChan || (numChannels == 1)) - { - chans[0] = dests[0]; - } - else if (useReaderRightChan) - { - chans[1] = dests[0]; - } + auto numTargetChannels = buffer->getNumChannels(); - read (chans, 2, readerStartSample, numSamples, true); + if (numTargetChannels <= 2) + { + int* dests[2] = { reinterpret_cast (buffer->getWritePointer (0, startSample)), + reinterpret_cast (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr) }; + int* chans[3] = {}; - // if the target's stereo and the source is mono, dupe the first channel.. - if (numTargetChannels > 1 - && (chans[0] == nullptr || chans[1] == nullptr) - && (dests[0] != nullptr && dests[1] != nullptr)) - { - memcpy (dests[1], dests[0], (size_t) numSamples * sizeof (float)); - } + if (useReaderLeftChan == useReaderRightChan) + { + chans[0] = dests[0]; - if (! usesFloatingPointData) - convertFixedToFloat (dests, 2, numSamples); + if (numChannels > 1) + chans[1] = dests[1]; } - else if (numTargetChannels <= 64) + else if (useReaderLeftChan || (numChannels == 1)) { - int* chans[65]; - readChannels (*this, chans, buffer, startSample, numSamples, - readerStartSample, numTargetChannels, ! usesFloatingPointData); + chans[0] = dests[0]; } - else + else if (useReaderRightChan) + { + chans[1] = dests[0]; + } + + if (! read (chans, 2, readerStartSample, numSamples, true)) + return false; + + // if the target's stereo and the source is mono, dupe the first channel.. + if (numTargetChannels > 1 + && (chans[0] == nullptr || chans[1] == nullptr) + && (dests[0] != nullptr && dests[1] != nullptr)) { - HeapBlock chans (numTargetChannels + 1); - readChannels (*this, chans, buffer, startSample, numSamples, - readerStartSample, numTargetChannels, ! usesFloatingPointData); + memcpy (dests[1], dests[0], (size_t) numSamples * sizeof (float)); } + + if (! usesFloatingPointData) + convertFixedToFloat (dests, 2, numSamples); + + return true; } + + if (numTargetChannels <= 64) + { + int* chans[65]; + return readChannels (*this, chans, buffer, startSample, numSamples, + readerStartSample, numTargetChannels, ! usesFloatingPointData); + } + + HeapBlock chans (numTargetChannels + 1); + + return readChannels (*this, chans, buffer, startSample, numSamples, + readerStartSample, numTargetChannels, ! usesFloatingPointData); } void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples, diff --git a/modules/juce_audio_formats/format/juce_AudioFormatReader.h b/modules/juce_audio_formats/format/juce_AudioFormatReader.h index bc404cea1a..3e7026a81c 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatReader.h +++ b/modules/juce_audio_formats/format/juce_AudioFormatReader.h @@ -132,8 +132,12 @@ public: the buffer's floating-point format, and will try to intelligently cope with mismatches between the number of channels in the reader and the buffer. + + @returns true if the operation succeeded, false if there was an error. Note + that reading sections of data beyond the extent of the stream isn't an + error - the reader should just return zeros for these regions */ - void read (AudioBuffer* buffer, + bool read (AudioBuffer* buffer, int startSampleInDestBuffer, int numSamples, int64 readerStartSample, diff --git a/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp b/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp index 85a619c4d9..86be28f15c 100644 --- a/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp +++ b/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp @@ -56,6 +56,8 @@ bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, const ScopedLock sl (lock); nextReadPosition = startSampleInFile; + bool allSamplesRead = true; + while (numSamples > 0) { if (auto block = getBlockContaining (startSampleInFile)) @@ -79,6 +81,8 @@ bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, startOffsetInDestBuffer += numToDo; startSampleInFile += numToDo; numSamples -= numToDo; + + allSamplesRead = allSamplesRead && block->allSamplesRead; } else { @@ -88,6 +92,7 @@ bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, if (auto* dest = (float*) destSamples[j]) FloatVectorOperations::clear (dest + startOffsetInDestBuffer, numSamples); + allSamplesRead = false; break; } else @@ -98,14 +103,14 @@ bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, } } - return true; + return allSamplesRead; } BufferingAudioReader::BufferedBlock::BufferedBlock (AudioFormatReader& reader, int64 pos, int numSamples) : range (pos, pos + numSamples), - buffer ((int) reader.numChannels, numSamples) + buffer ((int) reader.numChannels, numSamples), + allSamplesRead (reader.read (&buffer, 0, numSamples, pos, true, true)) { - reader.read (&buffer, 0, numSamples, pos, true, true); } BufferingAudioReader::BufferedBlock* BufferingAudioReader::getBlockContaining (int64 pos) const noexcept diff --git a/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h b/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h index 1b79469622..c906d98d71 100644 --- a/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h +++ b/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h @@ -66,6 +66,7 @@ private: Range range; AudioBuffer buffer; + bool allSamplesRead = false; }; int useTimeSlice() override;