From e71fd7cdcbe035ad1375aafed18357fac94dd682 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 22 Oct 2013 15:35:47 +0100 Subject: [PATCH] Fix for AudioFormatReader::read when passing buffers with > 2 channels. --- .../format/juce_AudioFormatReader.cpp | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp b/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp index 64aa3c7a89..1d2c845b1c 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp +++ b/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp @@ -100,6 +100,18 @@ bool AudioFormatReader::read (int* const* destSamples, return true; } +static void readChannels (AudioFormatReader& reader, + int** const chans, AudioSampleBuffer* const buffer, + const int startSample, const int numSamples, + const int64 readerStartSample, const int numTargetChannels) +{ + for (int j = 0; j < numTargetChannels; ++j) + chans[j] = reinterpret_cast (buffer->getSampleData (j, startSample)); + + chans[numTargetChannels] = nullptr; + reader.read (chans, numTargetChannels, readerStartSample, numSamples, true); +} + void AudioFormatReader::read (AudioSampleBuffer* buffer, int startSample, int numSamples, @@ -113,49 +125,51 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, if (numSamples > 0) { const int numTargetChannels = buffer->getNumChannels(); - int* chans[3]; - if (useReaderLeftChan == useReaderRightChan) + if (numTargetChannels <= 2) { - chans[0] = reinterpret_cast (buffer->getSampleData (0, startSample)); - chans[1] = (numChannels > 1 && numTargetChannels > 1) ? reinterpret_cast (buffer->getSampleData (1, startSample)) : nullptr; - } - else if (useReaderLeftChan || (numChannels == 1)) - { - chans[0] = reinterpret_cast (buffer->getSampleData (0, startSample)); - chans[1] = nullptr; - } - else if (useReaderRightChan) - { - chans[0] = nullptr; - chans[1] = reinterpret_cast (buffer->getSampleData (0, startSample)); - } + int* const dest0 = reinterpret_cast (buffer->getSampleData (0, startSample)); + int* const dest1 = reinterpret_cast (numTargetChannels > 1 ? buffer->getSampleData (1, startSample) : nullptr); + int* chans[3]; - chans[2] = nullptr; + if (useReaderLeftChan == useReaderRightChan) + { + chans[0] = dest0; + chans[1] = numChannels > 1 ? dest1 : nullptr; + } + else if (useReaderLeftChan || (numChannels == 1)) + { + chans[0] = dest0; + chans[1] = nullptr; + } + else if (useReaderRightChan) + { + chans[0] = nullptr; + chans[1] = dest0; + } - read (chans, 2, readerStartSample, numSamples, true); + chans[2] = nullptr; + read (chans, 2, readerStartSample, numSamples, true); + + // if the target's stereo and the source is mono, dupe the first channel.. + if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr)) + memcpy (dest1, dest0, sizeof (float) * (size_t) numSamples); + } + else if (numTargetChannels <= 64) + { + int* chans[65]; + readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); + } + else + { + HeapBlock chans (numTargetChannels); + readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); + } if (! usesFloatingPointData) - { - for (int j = 0; j < 2; ++j) - { - if (float* const d = reinterpret_cast (chans[j])) - { - const float multiplier = 1.0f / 0x7fffffff; - - for (int i = 0; i < numSamples; ++i) - d[i] = *reinterpret_cast (d + i) * multiplier; - } - } - } - - if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr)) - { - // if this is a stereo buffer and the source was mono, dupe the first channel.. - memcpy (buffer->getSampleData (1, startSample), - buffer->getSampleData (0, startSample), - sizeof (float) * (size_t) numSamples); - } + for (int j = 0; j < numTargetChannels; ++j) + if (float* const d = buffer->getSampleData (j, startSample)) + FloatVectorOperations::convertFixedToFloat (d, reinterpret_cast (d), 1.0f / 0x7fffffff, numSamples); } }