From fc2181aa22f129cffcfb3101743898a3d82bb873 Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 2 Jul 2009 15:11:45 +0000 Subject: [PATCH] changed the AudioFormatReader class to make the formats more consistent in the way they deal with requests for a different number of channels to the number that the file contains. This will mean that anyone who's using a custom AudioFormat will need to replace their read() method with a readSamples() method (easy to do - it's quite similar, with a couple of extra parameters, and actually makes things a bit easier for the subclass). --- .../juce_win32_AudioCDReader.cpp | 35 +- juce_amalgamated.cpp | 1154 ++++++++--------- juce_amalgamated.h | 95 +- .../juce_AiffAudioFormat.cpp | 560 ++++---- .../audio_file_formats/juce_AudioCDReader.cpp | 7 +- .../audio_file_formats/juce_AudioCDReader.h | 5 +- .../audio_file_formats/juce_AudioFormat.cpp | 69 +- .../juce_AudioFormatReader.h | 63 +- .../juce_AudioSubsectionReader.cpp | 27 +- .../juce_AudioSubsectionReader.h | 5 +- .../juce_FlacAudioFormat.cpp | 48 +- .../juce_OggVorbisAudioFormat.cpp | 49 +- .../juce_QuickTimeAudioFormat.cpp | 16 +- .../juce_WavAudioFormat.cpp | 286 ++-- .../audio/dsp/juce_AudioSampleBuffer.cpp | 2 +- 15 files changed, 1192 insertions(+), 1229 deletions(-) diff --git a/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp b/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp index d6ce635bfa..e86bfae4bb 100644 --- a/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp +++ b/build/win32/platform_specific_code/juce_win32_AudioCDReader.cpp @@ -1745,31 +1745,12 @@ AudioCDReader::~AudioCDReader() decUserCount(); } -bool AudioCDReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - CDDeviceWrapper* const device = (CDDeviceWrapper*)handle; + CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; bool ok = true; - int offset = 0; - - if (startSampleInFile < 0) - { - int* l = destSamples[0]; - int* r = destSamples[1]; - - numSamples += (int) startSampleInFile; - offset -= (int) startSampleInFile; - - while (++startSampleInFile <= 0) - { - *l++ = 0; - - if (r != 0) - *r++ = 0; - } - } while (numSamples > 0) { @@ -1781,8 +1762,8 @@ bool AudioCDReader::read (int** destSamples, { const int toDo = (int) jmin ((int64) numSamples, bufferEndSample - startSampleInFile); - int* const l = destSamples[0] + offset; - int* const r = destSamples[1] + offset; + int* const l = destSamples[0] + startOffsetInDestBuffer; + int* const r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; const short* src = (const short*) buffer.getData(); src += 2 * (startSampleInFile - bufferStartSample); @@ -1794,7 +1775,7 @@ bool AudioCDReader::read (int** destSamples, r[i] = src [(i << 1) + 1] << 16; } - offset += toDo; + startOffsetInDestBuffer += toDo; startSampleInFile += toDo; numSamples -= toDo; } @@ -1840,8 +1821,8 @@ bool AudioCDReader::read (int** destSamples, } else { - int* l = destSamples[0] + offset; - int* r = destSamples[1] + offset; + int* l = destSamples[0] + startOffsetInDestBuffer; + int* r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; while (--numSamples >= 0) { diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 1bbc06dbcf..2df8b9b633 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -7999,6 +7999,7 @@ void* juce_openInternetFile (const String& url, void juce_closeInternetFile (void* handle); int juce_readFromInternetFile (void* handle, void* dest, int bytesToRead); int juce_seekInInternetFile (void* handle, int newPosition); +int64 juce_getInternetFileContentLength (void* handle); class WebInputStream : public InputStream { @@ -8044,7 +8045,7 @@ public: int64 getTotalLength() { - return -1; + return juce_getInternetFileContentLength (handle); } bool isExhausted() @@ -17407,91 +17408,57 @@ public: { } - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int64 start = startSampleInFile; - int startOffsetInDestBuffer = 0; + numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile); - if (startSampleInFile < 0) + if (numSamples <= 0) + return true; + + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; + + while (numSamples > 0) { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - start = 0; - } - - int numToDo = jlimit (0, numSamples, (int) (lengthInSamples - start)); - - if (numToDo > 0) - { - input->setPosition (dataChunkStart + start * bytesPerFrame); - - int num = numToDo; int* left = destSamples[0]; if (left != 0) - left += startOffsetInDestBuffer; + left += startOffsetInDestBuffer; - int* right = destSamples[1]; + int* right = numDestChannels > 1 ? destSamples[1] : 0; if (right != 0) right += startOffsetInDestBuffer; - // (keep this a multiple of 3) - const int tempBufSize = 1440 * 4; - char tempBuffer [tempBufSize]; + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - while (num > 0) + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + + if (bitsPerSample == 16) { - const int numThisTime = jmin (tempBufSize / bytesPerFrame, num); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - - if (bitsPerSample == 16) + if (littleEndian) { - if (littleEndian) - { - const short* src = (const short*) tempBuffer; + const short* src = (const short*) tempBuffer; - if (numChannels > 1) + if (numChannels > 1) + { + if (left == 0) { - if (left == 0) + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - ++src; - } + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + ++src; + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } else @@ -17499,225 +17466,19 @@ public: for (int i = numThisTime; --i >= 0;) { *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } else { - const char* src = (const char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = bigEndianShort (src) << 16; - src += 4; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 2; - *left++ = bigEndianShort (src) << 16; - src += 2; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndianShort (src) << 16; - src += 2; - *right++ = bigEndianShort (src) << 16; - src += 2; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndianShort (src) << 16; - src += 2; - } + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } - else if (bitsPerSample == 24) - { - const char* src = (const char*)tempBuffer; - - if (littleEndian) - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = littleEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - *right++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = bigEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndian24Bit (src) << 8; - src += 3; - *right++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - } - } - else if (bitsPerSample == 32) - { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; - - if (littleEndian) - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfBigEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - } - } - } - else - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfLittleEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - *r++ = swapIfLittleEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - } - } - } - - left = (int*) l; - right = (int*) r; - } - else if (bitsPerSample == 8) + else { const char* src = (const char*) tempBuffer; @@ -17727,24 +17488,27 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = ((int) *src++) << 24; - ++src; + *right++ = bigEndianShort (src) << 16; + src += 4; } } else if (right == 0) { for (int i = numThisTime; --i >= 0;) { - ++src; - *left++ = ((int) *src++) << 24; + src += 2; + *left++ = bigEndianShort (src) << 16; + src += 2; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int) *src++) << 24; - *right++ = ((int) *src++) << 24; + *left++ = bigEndianShort (src) << 16; + src += 2; + *right++ = bigEndianShort (src) << 16; + src += 2; } } } @@ -17752,24 +17516,233 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int) *src++) << 24; + *left++ = bigEndianShort (src) << 16; + src += 2; + } + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*)tempBuffer; + + if (littleEndian) + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = littleEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = littleEndian24Bit (src) << 8; + src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = bigEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = bigEndian24Bit (src) << 8; + src += 3; + *right++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; + + if (littleEndian) + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = swapIfBigEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + *r++ = swapIfBigEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + } + } + } + else + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = swapIfLittleEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); + *r++ = swapIfLittleEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); } } } - num -= numThisTime; + left = (int*) l; + right = (int*) r; } + else if (bitsPerSample == 8) + { + const char* src = (const char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ((int) *src++) << 24; + ++src; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *left++ = ((int) *src++) << 24; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + *right++ = ((int) *src++) << 24; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + } + } + } + + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; } - if (numToDo < numSamples) + if (numSamples > 0) { - int** destChan = destSamples; - while (*destChan != 0) - { - zeromem ((*destChan) + (startOffsetInDestBuffer + numToDo), - sizeof (int) * (numSamples - numToDo)); - ++destChan; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; @@ -18206,9 +18179,8 @@ void AudioCDReader::refreshTrackLengths() lengthInSamples = sample; } -bool AudioCDReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { while (numSamples > 0) { @@ -18255,7 +18227,7 @@ bool AudioCDReader::read (int** destSamples, const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track)); const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos); - reader->read (destSamples, startPos, numAvailable); + reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable); numSamples -= numAvailable; startSampleInFile += numAvailable; @@ -18330,6 +18302,67 @@ AudioFormatReader::~AudioFormatReader() delete input; } +bool AudioFormatReader::read (int** destSamples, + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies) +{ + jassert (numDestChannels > 0); // you have to actually give this some channels to work with! + + int startOffsetInDestBuffer = 0; + + if (startSampleInSource < 0) + { + const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead); + + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * silence); + + startOffsetInDestBuffer += silence; + numSamplesToRead -= silence; + startSampleInSource = 0; + } + + if (numSamplesToRead <= 0) + return true; + + if (! readSamples (destSamples, jmin (numChannels, numDestChannels), startOffsetInDestBuffer, + startSampleInSource, numSamplesToRead)) + return false; + + if (numDestChannels > numChannels) + { + if (fillLeftoverChannelsWithCopies) + { + int* lastFullChannel = destSamples[0]; + + for (int i = numDestChannels; --i > 0;) + { + if (destSamples[i] != 0) + { + lastFullChannel = destSamples[i]; + break; + } + } + + if (lastFullChannel != 0) + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead); + } + else + { + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamplesToRead); + } + } + + return true; +} + static void findMaxMin (const float* src, const int num, float& maxVal, float& minVal) { @@ -18381,7 +18414,7 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, while (numSamples > 0) { const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, startSampleInFile, numToDo); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); numSamples -= numToDo; @@ -18419,7 +18452,7 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, while (numSamples > 0) { const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, startSampleInFile, numToDo); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); numSamples -= numToDo; @@ -18505,7 +18538,7 @@ int64 AudioFormatReader::searchForLevel (int64 startSample, if (bufferStart >= (int) lengthInSamples) break; - read ((int**) tempBuffer, bufferStart, numThisTime); + read ((int**) tempBuffer, 2, bufferStart, numThisTime, false); int num = numThisTime; while (--num >= 0) @@ -18624,7 +18657,7 @@ bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader, for (int i = tempBuffer.getNumChannels(); --i >= 0;) buffers[i] = (int*) tempBuffer.getSampleData (i, 0); - if (! reader.read (buffers, startSample, numToDo)) + if (! reader.read (buffers, maxChans, startSample, numToDo, false)) return false; if (reader.usesFloatingPointData != isFloatingPoint()) @@ -18990,26 +19023,23 @@ AudioSubsectionReader::~AudioSubsectionReader() delete source; } -bool AudioSubsectionReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - if (startSampleInFile < 0 || startSampleInFile + numSamples > length) + if (startSampleInFile + numSamples > length) { - int** d = destSamples; - while (*d != 0) - { - zeromem (*d, sizeof (int) * numSamples); - ++d; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamples); - startSampleInFile = jmax ((int64) 0, startSampleInFile); - numSamples = jmax (0, jmin (numSamples, (int) (length - startSampleInFile))); + numSamples = jmin (numSamples, (int) (length - startSampleInFile)); + + if (numSamples <= 0) + return true; } - return source->read (destSamples, - startSampleInFile + startSample, - numSamples); + return source->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, + startSampleInFile + startSample, numSamples); } void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile, @@ -20053,33 +20083,31 @@ public: #endif } - bool read (int** destSamples, - int64 startSample, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { checkThreadIsAttached(); - int done = 0; while (numSamples > 0) { - if (! loadFrame ((int) startSample)) + if (! loadFrame ((int) startSampleInFile)) return false; const int numToDo = jmin (numSamples, samplesPerFrame); - for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j) + for (int j = numDestChannels; --j >= 0;) { if (destSamples[j] != 0) { const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; for (int i = 0; i < numToDo; ++i) - destSamples[j][done + i] = src [i << 1] << 16; + destSamples[j][startOffsetInDestBuffer + i] = src [i << 1] << 16; } } - done += numToDo; - startSample += numToDo; + startOffsetInDestBuffer += numToDo; + startSampleInFile += numToDo; numSamples -= numToDo; } @@ -20491,89 +20519,55 @@ public: { } - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int64 start = startSampleInFile; - int startOffsetInDestBuffer = 0; + numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile); - if (startSampleInFile < 0) + if (numSamples <= 0) + return true; + + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; + + while (numSamples > 0) { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - start = 0; - } - - const int numToDo = (int) jlimit ((int64) 0, (int64) numSamples, lengthInSamples - start); - - if (numToDo > 0) - { - input->setPosition (dataChunkStart + start * bytesPerFrame); - - int num = numToDo; int* left = destSamples[0]; if (left != 0) - left += startOffsetInDestBuffer; + left += startOffsetInDestBuffer; - int* right = destSamples[1]; + int* right = numDestChannels > 1 ? destSamples[1] : 0; if (right != 0) right += startOffsetInDestBuffer; - // (keep this a multiple of 3) - const int tempBufSize = 1440 * 4; - char tempBuffer [tempBufSize]; + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - while (num > 0) + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + + if (bitsPerSample == 16) { - const int numThisTime = jmin (tempBufSize / bytesPerFrame, num); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); + const short* src = (const short*) tempBuffer; - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - - if (bitsPerSample == 16) + if (numChannels > 1) { - const short* src = (const short*) tempBuffer; - - if (numChannels > 1) + if (left == 0) { - if (left == 0) + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + ++src; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) swapIfBigEndian ((unsigned short) *src++) - + (int) swapIfBigEndian ((unsigned short) *src++)) << 15; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; } } else @@ -20581,40 +20575,39 @@ public: for (int i = numThisTime; --i >= 0;) { *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } - else if (bitsPerSample == 24) + else { - const char* src = (const char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - src += 6; - *right++ = littleEndian24Bit (src) << 8; - } + src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (littleEndian24Bit (src) + littleEndian24Bit (src + 3)) << 7; - src += 6; - } - } - else - { - for (int i = 0; i < numThisTime; ++i) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - *right++ = littleEndian24Bit (src) << 8; - src += 3; - } + *left++ = littleEndian24Bit (src) << 8; + src += 6; } } else @@ -20623,40 +20616,42 @@ public: { *left++ = littleEndian24Bit (src) << 8; src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; } } } - else if (bitsPerSample == 32) + else { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; - - if (numChannels > 1) + for (int i = 0; i < numThisTime; ++i) { - if (l == 0) + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; + + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfBigEndian (*src++); - } + ++src; + *r++ = swapIfBigEndian (*src++); } - else if (r == 0) + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *l++ = (swapIfBigEndian (*src++) >> 1) - + (swapIfBigEndian (*src++) >> 1); - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); - } + *l++ = swapIfBigEndian (*src++); + ++src; } } else @@ -20664,66 +20659,71 @@ public: for (int i = numThisTime; --i >= 0;) { *l++ = swapIfBigEndian (*src++); + *r++ = swapIfBigEndian (*src++); } } - - left = (int*)l; - right = (int*)r; } - else if (bitsPerSample == 8) + else { - const unsigned char* src = (const unsigned char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) + *l++ = swapIfBigEndian (*src++); + } + } + + left = (int*)l; + right = (int*)r; + } + else if (bitsPerSample == 8) + { + const unsigned char* src = (const unsigned char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = ((int) *src++ - 128) << 24; - } + ++src; + *right++ = ((int) *src++ - 128) << 24; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - *right++ = ((int) *src++ - 128) << 24; - } + *left++ = ((int) *src++ - 128) << 24; + ++src; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int)*src++ - 128) << 24; + *left++ = ((int) *src++ - 128) << 24; + *right++ = ((int) *src++ - 128) << 24; } } } - - num -= numThisTime; + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int)*src++ - 128) << 24; + } + } } + + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; } - if (numToDo < numSamples) + if (numSamples > 0) { - int** destChan = destSamples; - - while (*destChan != 0) - { - zeromem ((*destChan) + (startOffsetInDestBuffer + numToDo), - sizeof (int) * (numSamples - numToDo)); - ++destChan; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; @@ -24817,7 +24817,7 @@ void AudioSampleBuffer::readFromAudioReader (AudioFormatReader* reader, chans[2] = 0; - reader->read (chans, readerStartSample, numSamples); + reader->read (chans, 2, readerStartSample, numSamples, true); if (! reader->usesFloatingPointData) { @@ -44391,11 +44391,21 @@ void Label::showEditor() resized(); repaint(); + editorShown (editor); + enterModalState(); editor->grabKeyboardFocus(); } } +void Label::editorShown (TextEditor* editorComponent) +{ +} + +void Label::editorAboutToBeHidden (TextEditor* editorComponent) +{ +} + bool Label::updateFromTextEditorContents() { jassert (editor != 0); @@ -44421,6 +44431,8 @@ void Label::hideEditor (const bool discardCurrentEditorContents) { if (editor != 0) { + editorAboutToBeHidden (editor); + const bool changed = (! discardCurrentEditorContents) && updateFromTextEditorContents(); @@ -62231,9 +62243,18 @@ Button* LookAndFeel::createSliderButton (const bool isIncrement) return new TextButton (isIncrement ? "+" : "-", String::empty); } +class SliderLabelComp : public Label +{ +public: + SliderLabelComp() : Label (String::empty, String::empty) {} + ~SliderLabelComp() {} + + void mouseWheelMove (const MouseEvent&, float, float) {} +}; + Label* LookAndFeel::createSliderTextBox (Slider& slider) { - Label* const l = new Label (T("n"), String::empty); + Label* const l = new SliderLabelComp(); l->setJustificationType (Justification::centred); @@ -81365,8 +81386,8 @@ private: y2 = lastY + (lastY - lastY2); path.cubicTo (x2, y2, x, y, x3, y3); - lastX2 = x2; - lastY2 = y2; + lastX2 = x; + lastY2 = y; lastX = x3; lastY = y3; } @@ -126863,33 +126884,14 @@ public: } // returns the number of samples read - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { using namespace FlacNamespace; if (! ok) return false; - int offset = 0; - - if (startSampleInFile < 0) - { - const int num = (int) jmin ((int64) numSamples, -startSampleInFile); - - int n = 0; - while (destSamples[n] != 0) - { - zeromem (destSamples[n], sizeof (int) * num); - ++n; - } - - offset += num; - startSampleInFile += num; - numSamples -= num; - } - while (numSamples > 0) { if (startSampleInFile >= reservoirStart @@ -126900,16 +126902,13 @@ public: jassert (num > 0); - int n = 0; - while (destSamples[n] != 0) - { - memcpy (destSamples[n] + offset, - reservoir.getSampleData (n, (int) (startSampleInFile - reservoirStart)), - sizeof (int) * num); - ++n; - } + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (int) * num); - offset += num; + startOffsetInDestBuffer += num; startSampleInFile += num; numSamples -= num; } @@ -126945,12 +126944,10 @@ public: if (numSamples > 0) { - int n = 0; - while (destSamples[n] != 0) - { - zeromem (destSamples[n] + offset, sizeof (int) * numSamples); - ++n; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; @@ -191313,31 +191310,9 @@ public: ov_clear (&ovFile); } - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int startOffsetInDestBuffer = 0; - - if (startSampleInFile < 0) - { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - } - while (numSamples > 0) { const int numAvailable = reservoirStart + samplesInReservoir - startSampleInFile; @@ -191348,16 +191323,11 @@ public: const int numToUse = jmin (numSamples, numAvailable); - for (unsigned int i = 0; i < numChannels; ++i) - { - if (destSamples[i] == 0) - break; - - memcpy (destSamples[i] + startOffsetInDestBuffer, - reservoir.getSampleData (jmin (i, reservoir.getNumChannels()), - (int) (startSampleInFile - reservoirStart)), - sizeof (float) * numToUse); - } + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (float) * numToUse); startSampleInFile += numToUse; numSamples -= numToUse; @@ -191408,6 +191378,14 @@ public: } } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } + return true; } @@ -242882,9 +242860,9 @@ int juce_seekInInternetFile (void* handle, int newPosition) } } -int juce_getInternetFileContentLength (void* handle) +int64 juce_getInternetFileContentLength (void* handle) { - DWORD result = 0; + DWORD result = -1; const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; if (crs != 0) @@ -250889,31 +250867,12 @@ AudioCDReader::~AudioCDReader() decUserCount(); } -bool AudioCDReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - CDDeviceWrapper* const device = (CDDeviceWrapper*)handle; + CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; bool ok = true; - int offset = 0; - - if (startSampleInFile < 0) - { - int* l = destSamples[0]; - int* r = destSamples[1]; - - numSamples += (int) startSampleInFile; - offset -= (int) startSampleInFile; - - while (++startSampleInFile <= 0) - { - *l++ = 0; - - if (r != 0) - *r++ = 0; - } - } while (numSamples > 0) { @@ -250925,8 +250884,8 @@ bool AudioCDReader::read (int** destSamples, { const int toDo = (int) jmin ((int64) numSamples, bufferEndSample - startSampleInFile); - int* const l = destSamples[0] + offset; - int* const r = destSamples[1] + offset; + int* const l = destSamples[0] + startOffsetInDestBuffer; + int* const r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; const short* src = (const short*) buffer.getData(); src += 2 * (startSampleInFile - bufferStartSample); @@ -250938,7 +250897,7 @@ bool AudioCDReader::read (int** destSamples, r[i] = src [(i << 1) + 1] << 16; } - offset += toDo; + startOffsetInDestBuffer += toDo; startSampleInFile += toDo; numSamples -= toDo; } @@ -250984,8 +250943,8 @@ bool AudioCDReader::read (int** destSamples, } else { - int* l = destSamples[0] + offset; - int* r = destSamples[1] + offset; + int* l = destSamples[0] + startOffsetInDestBuffer; + int* r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; while (--numSamples >= 0) { @@ -258073,8 +258032,7 @@ public: // NB - using charToString() here instead of just T(" "), because that was // causing a mysterious gcc internal compiler error... const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false) - .substring (0, 3) - .getIntValue(); + .substring (0, 3).getIntValue(); //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); @@ -258302,7 +258260,7 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) return 0; } -int juce_getInternetFileContentLength (void* handle) +int64 juce_getInternetFileContentLength (void* handle) { JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; @@ -258312,7 +258270,7 @@ int juce_getInternetFileContentLength (void* handle) jassertfalse } - return 0; + return -1; } int juce_seekInInternetFile (void* handle, int newPosition) @@ -259367,7 +259325,7 @@ public: if (inputChannels.getHighestBit() >= 0) { - for (int i = 0; i <= inputChannels.getHighestBit(); ++i) + for (int i = 0; i <= jmax (inputChannels.getHighestBit(), minChansIn); ++i) { inputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize); @@ -266516,6 +266474,7 @@ using namespace JUCE_NAMESPACE; Thread* runLoopThread; bool initialised, hasFailed, hasFinished; int position; + int64 contentLength; NSLock* dataLock; } @@ -266577,6 +266536,7 @@ public: initialised = false; hasFailed = false; hasFinished = false; + contentLength = -1; runLoopThread = new JuceURLConnectionMessageThread (self); runLoopThread->startThread(); @@ -266619,6 +266579,7 @@ public: [data setLength: 0]; [dataLock unlock]; initialised = true; + contentLength = [response expectedContentLength]; } - (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error @@ -266776,17 +266737,14 @@ int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) return 0; } -int juce_getInternetFileContentLength (void* handle) +int64 juce_getInternetFileContentLength (void* handle) { JuceURLConnection* const s = (JuceURLConnection*) handle; if (s != 0) - { - //xxx todo - jassertfalse - } + return s->contentLength; - return 0; + return -1; } int juce_seekInInternetFile (void* handle, int newPosition) diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 749a6fedc6..62feb81486 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -3291,8 +3291,8 @@ public: @see ArrayAllocationBase */ - OwnedArray (const int granularity_ = juceDefaultArrayGranularity) throw() - : ArrayAllocationBase (granularity_), + OwnedArray (const int granularity = juceDefaultArrayGranularity) throw() + : ArrayAllocationBase (granularity), numUsed (0) { } @@ -4567,8 +4567,8 @@ public: @see ArrayAllocationBase */ - Array (const int granularity_ = juceDefaultArrayGranularity) throw() - : ArrayAllocationBase (granularity_), + Array (const int granularity = juceDefaultArrayGranularity) throw() + : ArrayAllocationBase (granularity), numUsed (0) { } @@ -10484,8 +10484,8 @@ public: @see ArrayAllocationBase */ - SortedSet (const int granularity_ = juceDefaultArrayGranularity) throw() - : ArrayAllocationBase (granularity_), + SortedSet (const int granularity = juceDefaultArrayGranularity) throw() + : ArrayAllocationBase (granularity), numUsed (0) { } @@ -31519,28 +31519,37 @@ public: range -1.0 to 1.0 or beyond) If the format is stereo, then destSamples[0] is the left channel data, and destSamples[1] is the right channel. - The array passed in should be zero-terminated, and it's ok to - pass in an array with a different number of channels than - the number in the stream, so if you pass in an array with only - one channel and the stream is stereo, the reader will - put a merged sum of the stereo channels into the single - destination channel. - @param startSample the offset into the audio stream from which the samples + The numDestChannels parameter indicates how many pointers this array + contains, but some of these pointers can be null if you don't want to + read data for some of the channels + @param numDestChannels the number of array elements in the destChannels array + @param startSampleInSource the position in the audio file or stream at which the samples should be read, as a number of samples from the start of the stream. It's ok for this to be beyond the start or end of the - available data - any samples that can't be read will be padded - with zeros. - @param numSamples the number of samples to read. If this is greater than the - number of samples available, the result will be padded with - zeros + available data - any samples that are out-of-range will be returned + as zeros. + @param numSamplesToRead the number of samples to read. If this is greater than the number + of samples that the file or stream contains. the result will be padded + with zeros + @param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available + for some of the channels that you pass in, then they should be filled with + copies of valid source channels. + E.g. if you're reading a mono file and you pass 2 channels to this method, then + if fillLeftoverChannelsWithCopies is true, both destination channels will be filled + with the same data from the file's single channel. If fillLeftoverChannelsWithCopies + was false, then only the first channel would be filled with the file's contents, and + the second would be cleared. If there are many channels, e.g. you try to read 4 channels + from a stereo file, then the last 3 would all end up with copies of the same data. @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 @see readMaxLevels */ - virtual bool read (int** destSamples, - int64 startSample, - int numSamples) = 0; + bool read (int** destSamples, + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies); /** Finds the highest and lowest sample levels from a section of the audio stream. @@ -31620,6 +31629,27 @@ public: /** The input stream, for use by subclasses. */ InputStream* input; + /** Subclasses must implement this method to perform the low-level read operation. + + Callers should use read() instead of calling this directly. + + @param destSamples the array of destination buffers to fill. Some of these + pointers may be null + @param numDestChannels the number of items in the destSamples array. This + value is guaranteed not to be greater than the number of + channels that this reader object contains + @param startOffsetInDestBuffer the number of samples from the start of the + dest data at which to begin writing + @param startSampleInFile the number of samples into the source data at which + to begin reading. This value is guaranteed to be >= 0. + @param numSamples the number of samples to read + */ + virtual bool readSamples (int** destSamples, + int numDestChannels, + int startOffsetInDestBuffer, + int64 startSampleInFile, + int numSamples) = 0; + juce_UseDebuggingNewOperator private: @@ -33915,6 +33945,15 @@ protected: */ virtual void textWasChanged(); + /** Called when the text editor has just appeared, due to a user click or other + focus change. + */ + virtual void editorShown (TextEditor* editorComponent); + + /** Called when the text editor is going to be deleted, after editing has finished. + */ + virtual void editorAboutToBeHidden (TextEditor* editorComponent); + private: String text; Font font; @@ -36861,9 +36900,8 @@ public: ~AudioCDReader(); /** Implementation of the AudioFormatReader method. */ - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); /** Checks whether the CD has been removed from the drive. */ @@ -37138,9 +37176,8 @@ public: /** Destructor. */ ~AudioSubsectionReader(); - bool read (int** destSamples, - int64 startSample, - int numSamples); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); void readMaxLevels (int64 startSample, int64 numSamples, @@ -50568,7 +50605,7 @@ class FilenameComponent; Use FilenameComponent::addListener() and FilenameComponent::removeListener() to register one of these objects for event callbacks when the filename is changed. - @See FilenameComponent + @see FilenameComponent */ class JUCE_API FilenameComponentListener { @@ -53750,7 +53787,7 @@ public: const bool isMouseOverButton, const bool isButtonDown); - /** AlertWindow handling.. + /* AlertWindow handling.. */ virtual AlertWindow* createAlertWindow (const String& title, const String& message, diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.cpp index 657f240f64..20117ac2f3 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AiffAudioFormat.cpp @@ -158,91 +158,57 @@ public: } //============================================================================== - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int64 start = startSampleInFile; - int startOffsetInDestBuffer = 0; + numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile); + + if (numSamples <= 0) + return true; - if (startSampleInFile < 0) + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; + + while (numSamples > 0) { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - start = 0; - } - - int numToDo = jlimit (0, numSamples, (int) (lengthInSamples - start)); - - if (numToDo > 0) - { - input->setPosition (dataChunkStart + start * bytesPerFrame); - - int num = numToDo; int* left = destSamples[0]; if (left != 0) - left += startOffsetInDestBuffer; + left += startOffsetInDestBuffer; - int* right = destSamples[1]; + int* right = numDestChannels > 1 ? destSamples[1] : 0; if (right != 0) right += startOffsetInDestBuffer; - // (keep this a multiple of 3) - const int tempBufSize = 1440 * 4; - char tempBuffer [tempBufSize]; + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - while (num > 0) + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + + if (bitsPerSample == 16) { - const int numThisTime = jmin (tempBufSize / bytesPerFrame, num); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - - if (bitsPerSample == 16) + if (littleEndian) { - if (littleEndian) - { - const short* src = (const short*) tempBuffer; + const short* src = (const short*) tempBuffer; - if (numChannels > 1) + if (numChannels > 1) + { + if (left == 0) { - if (left == 0) + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - ++src; - } + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + ++src; + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } else @@ -250,225 +216,19 @@ public: for (int i = numThisTime; --i >= 0;) { *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } else { - const char* src = (const char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = bigEndianShort (src) << 16; - src += 4; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 2; - *left++ = bigEndianShort (src) << 16; - src += 2; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndianShort (src) << 16; - src += 2; - *right++ = bigEndianShort (src) << 16; - src += 2; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndianShort (src) << 16; - src += 2; - } + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } - else if (bitsPerSample == 24) - { - const char* src = (const char*)tempBuffer; - - if (littleEndian) - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = littleEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - *right++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = bigEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndian24Bit (src) << 8; - src += 3; - *right++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = bigEndian24Bit (src) << 8; - src += 3; - } - } - } - } - else if (bitsPerSample == 32) - { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; - - if (littleEndian) - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfBigEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - } - } - } - else - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfLittleEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - *r++ = swapIfLittleEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfLittleEndian (*src++); - } - } - } - - left = (int*) l; - right = (int*) r; - } - else if (bitsPerSample == 8) + else { const char* src = (const char*) tempBuffer; @@ -478,24 +238,27 @@ public: { for (int i = numThisTime; --i >= 0;) { - *right++ = ((int) *src++) << 24; - ++src; + *right++ = bigEndianShort (src) << 16; + src += 4; } } else if (right == 0) { for (int i = numThisTime; --i >= 0;) { - ++src; - *left++ = ((int) *src++) << 24; + src += 2; + *left++ = bigEndianShort (src) << 16; + src += 2; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int) *src++) << 24; - *right++ = ((int) *src++) << 24; + *left++ = bigEndianShort (src) << 16; + src += 2; + *right++ = bigEndianShort (src) << 16; + src += 2; } } } @@ -503,24 +266,233 @@ public: { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int) *src++) << 24; + *left++ = bigEndianShort (src) << 16; + src += 2; + } + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*)tempBuffer; + + if (littleEndian) + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = littleEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = littleEndian24Bit (src) << 8; + src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = bigEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = bigEndian24Bit (src) << 8; + src += 3; + *right++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = bigEndian24Bit (src) << 8; + src += 3; + } + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; + + if (littleEndian) + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = swapIfBigEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + *r++ = swapIfBigEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfBigEndian (*src++); + } + } + } + else + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = swapIfLittleEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); + *r++ = swapIfLittleEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = swapIfLittleEndian (*src++); } } } - num -= numThisTime; + left = (int*) l; + right = (int*) r; } + else if (bitsPerSample == 8) + { + const char* src = (const char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ((int) *src++) << 24; + ++src; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *left++ = ((int) *src++) << 24; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + *right++ = ((int) *src++) << 24; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + } + } + } + + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; } - if (numToDo < numSamples) + if (numSamples > 0) { - int** destChan = destSamples; - while (*destChan != 0) - { - zeromem ((*destChan) + (startOffsetInDestBuffer + numToDo), - sizeof (int) * (numSamples - numToDo)); - ++destChan; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.cpp index d4bf2bd0f4..405d639f02 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.cpp @@ -149,9 +149,8 @@ void AudioCDReader::refreshTrackLengths() lengthInSamples = sample; } -bool AudioCDReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { while (numSamples > 0) { @@ -198,7 +197,7 @@ bool AudioCDReader::read (int** destSamples, const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track)); const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos); - reader->read (destSamples, startPos, numAvailable); + reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable); numSamples -= numAvailable; startSampleInFile += numAvailable; diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h index 229fdd7680..a57b00b8f8 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioCDReader.h @@ -76,9 +76,8 @@ public: ~AudioCDReader(); /** Implementation of the AudioFormatReader method. */ - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); /** Checks whether the CD has been removed from the drive. */ diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp index 13332b63c8..ed29cd91bb 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormat.cpp @@ -55,6 +55,67 @@ AudioFormatReader::~AudioFormatReader() delete input; } +bool AudioFormatReader::read (int** destSamples, + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies) +{ + jassert (numDestChannels > 0); // you have to actually give this some channels to work with! + + int startOffsetInDestBuffer = 0; + + if (startSampleInSource < 0) + { + const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead); + + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * silence); + + startOffsetInDestBuffer += silence; + numSamplesToRead -= silence; + startSampleInSource = 0; + } + + if (numSamplesToRead <= 0) + return true; + + if (! readSamples (destSamples, jmin (numChannels, numDestChannels), startOffsetInDestBuffer, + startSampleInSource, numSamplesToRead)) + return false; + + if (numDestChannels > numChannels) + { + if (fillLeftoverChannelsWithCopies) + { + int* lastFullChannel = destSamples[0]; + + for (int i = numDestChannels; --i > 0;) + { + if (destSamples[i] != 0) + { + lastFullChannel = destSamples[i]; + break; + } + } + + if (lastFullChannel != 0) + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead); + } + else + { + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamplesToRead); + } + } + + return true; +} + static void findMaxMin (const float* src, const int num, float& maxVal, float& minVal) { @@ -106,7 +167,7 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, while (numSamples > 0) { const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, startSampleInFile, numToDo); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); numSamples -= numToDo; @@ -144,7 +205,7 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, while (numSamples > 0) { const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, startSampleInFile, numToDo); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); numSamples -= numToDo; @@ -230,7 +291,7 @@ int64 AudioFormatReader::searchForLevel (int64 startSample, if (bufferStart >= (int) lengthInSamples) break; - read ((int**) tempBuffer, bufferStart, numThisTime); + read ((int**) tempBuffer, 2, bufferStart, numThisTime, false); int num = numThisTime; while (--num >= 0) @@ -350,7 +411,7 @@ bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader, for (int i = tempBuffer.getNumChannels(); --i >= 0;) buffers[i] = (int*) tempBuffer.getSampleData (i, 0); - if (! reader.read (buffers, startSample, numToDo)) + if (! reader.read (buffers, maxChans, startSample, numToDo, false)) return false; if (reader.usesFloatingPointData != isFloatingPoint()) diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormatReader.h b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormatReader.h index ba54597121..367e400f4c 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioFormatReader.h +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioFormatReader.h @@ -86,28 +86,37 @@ public: range -1.0 to 1.0 or beyond) If the format is stereo, then destSamples[0] is the left channel data, and destSamples[1] is the right channel. - The array passed in should be zero-terminated, and it's ok to - pass in an array with a different number of channels than - the number in the stream, so if you pass in an array with only - one channel and the stream is stereo, the reader will - put a merged sum of the stereo channels into the single - destination channel. - @param startSample the offset into the audio stream from which the samples + The numDestChannels parameter indicates how many pointers this array + contains, but some of these pointers can be null if you don't want to + read data for some of the channels + @param numDestChannels the number of array elements in the destChannels array + @param startSampleInSource the position in the audio file or stream at which the samples should be read, as a number of samples from the start of the stream. It's ok for this to be beyond the start or end of the - available data - any samples that can't be read will be padded - with zeros. - @param numSamples the number of samples to read. If this is greater than the - number of samples available, the result will be padded with - zeros + available data - any samples that are out-of-range will be returned + as zeros. + @param numSamplesToRead the number of samples to read. If this is greater than the number + of samples that the file or stream contains. the result will be padded + with zeros + @param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available + for some of the channels that you pass in, then they should be filled with + copies of valid source channels. + E.g. if you're reading a mono file and you pass 2 channels to this method, then + if fillLeftoverChannelsWithCopies is true, both destination channels will be filled + with the same data from the file's single channel. If fillLeftoverChannelsWithCopies + was false, then only the first channel would be filled with the file's contents, and + the second would be cleared. If there are many channels, e.g. you try to read 4 channels + from a stereo file, then the last 3 would all end up with copies of the same data. @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 @see readMaxLevels */ - virtual bool read (int** destSamples, - int64 startSample, - int numSamples) = 0; + bool read (int** destSamples, + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies); /** Finds the highest and lowest sample levels from a section of the audio stream. @@ -188,6 +197,30 @@ public: /** The input stream, for use by subclasses. */ InputStream* input; + + //============================================================================== + /** Subclasses must implement this method to perform the low-level read operation. + + Callers should use read() instead of calling this directly. + + @param destSamples the array of destination buffers to fill. Some of these + pointers may be null + @param numDestChannels the number of items in the destSamples array. This + value is guaranteed not to be greater than the number of + channels that this reader object contains + @param startOffsetInDestBuffer the number of samples from the start of the + dest data at which to begin writing + @param startSampleInFile the number of samples into the source data at which + to begin reading. This value is guaranteed to be >= 0. + @param numSamples the number of samples to read + */ + virtual bool readSamples (int** destSamples, + int numDestChannels, + int startOffsetInDestBuffer, + int64 startSampleInFile, + int numSamples) = 0; + + //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.cpp b/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.cpp index 29aa4b3fc4..adbbf0806d 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.cpp @@ -62,26 +62,23 @@ AudioSubsectionReader::~AudioSubsectionReader() } //============================================================================== -bool AudioSubsectionReader::read (int** destSamples, - int64 startSampleInFile, - int numSamples) +bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - if (startSampleInFile < 0 || startSampleInFile + numSamples > length) + if (startSampleInFile + numSamples > length) { - int** d = destSamples; - while (*d != 0) - { - zeromem (*d, sizeof (int) * numSamples); - ++d; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamples); - startSampleInFile = jmax ((int64) 0, startSampleInFile); - numSamples = jmax (0, jmin (numSamples, (int) (length - startSampleInFile))); + numSamples = jmin (numSamples, (int) (length - startSampleInFile)); + + if (numSamples <= 0) + return true; } - return source->read (destSamples, - startSampleInFile + startSample, - numSamples); + return source->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, + startSampleInFile + startSample, numSamples); } void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile, diff --git a/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h b/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h index d3cc155f73..5c6f821bcc 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h +++ b/src/juce_appframework/audio/audio_file_formats/juce_AudioSubsectionReader.h @@ -73,9 +73,8 @@ public: //============================================================================== - bool read (int** destSamples, - int64 startSample, - int numSamples); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); void readMaxLevels (int64 startSample, int64 numSamples, diff --git a/src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp index 3b817cf88e..5f99eee978 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_FlacAudioFormat.cpp @@ -153,33 +153,14 @@ public: } // returns the number of samples read - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { using namespace FlacNamespace; if (! ok) return false; - int offset = 0; - - if (startSampleInFile < 0) - { - const int num = (int) jmin ((int64) numSamples, -startSampleInFile); - - int n = 0; - while (destSamples[n] != 0) - { - zeromem (destSamples[n], sizeof (int) * num); - ++n; - } - - offset += num; - startSampleInFile += num; - numSamples -= num; - } - while (numSamples > 0) { if (startSampleInFile >= reservoirStart @@ -190,16 +171,13 @@ public: jassert (num > 0); - int n = 0; - while (destSamples[n] != 0) - { - memcpy (destSamples[n] + offset, - reservoir.getSampleData (n, (int) (startSampleInFile - reservoirStart)), - sizeof (int) * num); - ++n; - } + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (int) * num); - offset += num; + startOffsetInDestBuffer += num; startSampleInFile += num; numSamples -= num; } @@ -235,12 +213,10 @@ public: if (numSamples > 0) { - int n = 0; - while (destSamples[n] != 0) - { - zeromem (destSamples[n] + offset, sizeof (int) * numSamples); - ++n; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; diff --git a/src/juce_appframework/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp index f39d07bffa..250638b217 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp @@ -137,31 +137,9 @@ public: } //============================================================================== - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int startOffsetInDestBuffer = 0; - - if (startSampleInFile < 0) - { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - } - while (numSamples > 0) { const int numAvailable = reservoirStart + samplesInReservoir - startSampleInFile; @@ -172,16 +150,11 @@ public: const int numToUse = jmin (numSamples, numAvailable); - for (unsigned int i = 0; i < numChannels; ++i) - { - if (destSamples[i] == 0) - break; - - memcpy (destSamples[i] + startOffsetInDestBuffer, - reservoir.getSampleData (jmin (i, reservoir.getNumChannels()), - (int) (startSampleInFile - reservoirStart)), - sizeof (float) * numToUse); - } + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (float) * numToUse); startSampleInFile += numToUse; numSamples -= numToUse; @@ -232,6 +205,14 @@ public: } } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } + return true; } diff --git a/src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp index 498212872d..3fe52f2a19 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp @@ -237,33 +237,31 @@ public: #endif } - bool read (int** destSamples, - int64 startSample, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { checkThreadIsAttached(); - int done = 0; while (numSamples > 0) { - if (! loadFrame ((int) startSample)) + if (! loadFrame ((int) startSampleInFile)) return false; const int numToDo = jmin (numSamples, samplesPerFrame); - for (unsigned int j = 0; j < inputStreamDesc.mChannelsPerFrame; ++j) + for (int j = numDestChannels; --j >= 0;) { if (destSamples[j] != 0) { const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; for (int i = 0; i < numToDo; ++i) - destSamples[j][done + i] = src [i << 1] << 16; + destSamples[j][startOffsetInDestBuffer + i] = src [i << 1] << 16; } } - done += numToDo; - startSample += numToDo; + startOffsetInDestBuffer += numToDo; + startSampleInFile += numToDo; numSamples -= numToDo; } diff --git a/src/juce_appframework/audio/audio_file_formats/juce_WavAudioFormat.cpp b/src/juce_appframework/audio/audio_file_formats/juce_WavAudioFormat.cpp index 666aed35b5..e53aa473a7 100644 --- a/src/juce_appframework/audio/audio_file_formats/juce_WavAudioFormat.cpp +++ b/src/juce_appframework/audio/audio_file_formats/juce_WavAudioFormat.cpp @@ -310,89 +310,55 @@ public: } //============================================================================== - bool read (int** destSamples, - int64 startSampleInFile, - int numSamples) + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) { - int64 start = startSampleInFile; - int startOffsetInDestBuffer = 0; + numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile); - if (startSampleInFile < 0) + if (numSamples <= 0) + return true; + + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; + + while (numSamples > 0) { - const int silence = (int) jmin (-startSampleInFile, (int64) numSamples); - - int** destChan = destSamples; - - for (int i = 2; --i >= 0;) - { - if (*destChan != 0) - { - zeromem (*destChan, sizeof (int) * silence); - ++destChan; - } - } - - startOffsetInDestBuffer += silence; - numSamples -= silence; - start = 0; - } - - const int numToDo = (int) jlimit ((int64) 0, (int64) numSamples, lengthInSamples - start); - - if (numToDo > 0) - { - input->setPosition (dataChunkStart + start * bytesPerFrame); - - int num = numToDo; int* left = destSamples[0]; if (left != 0) - left += startOffsetInDestBuffer; + left += startOffsetInDestBuffer; - int* right = destSamples[1]; + int* right = numDestChannels > 1 ? destSamples[1] : 0; if (right != 0) right += startOffsetInDestBuffer; - // (keep this a multiple of 3) - const int tempBufSize = 1440 * 4; - char tempBuffer [tempBufSize]; + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - while (num > 0) + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + + if (bitsPerSample == 16) { - const int numThisTime = jmin (tempBufSize / bytesPerFrame, num); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); + const short* src = (const short*) tempBuffer; - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - - if (bitsPerSample == 16) + if (numChannels > 1) { - const short* src = (const short*) tempBuffer; - - if (numChannels > 1) + if (left == 0) { - if (left == 0) + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + ++src; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) swapIfBigEndian ((unsigned short) *src++) - + (int) swapIfBigEndian ((unsigned short) *src++)) << 15; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; - } + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; } } else @@ -400,40 +366,39 @@ public: for (int i = numThisTime; --i >= 0;) { *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; } } } - else if (bitsPerSample == 24) + else { - const char* src = (const char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) + *left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - src += 6; - *right++ = littleEndian24Bit (src) << 8; - } + src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (littleEndian24Bit (src) + littleEndian24Bit (src + 3)) << 7; - src += 6; - } - } - else - { - for (int i = 0; i < numThisTime; ++i) - { - *left++ = littleEndian24Bit (src) << 8; - src += 3; - *right++ = littleEndian24Bit (src) << 8; - src += 3; - } + *left++ = littleEndian24Bit (src) << 8; + src += 6; } } else @@ -442,40 +407,42 @@ public: { *left++ = littleEndian24Bit (src) << 8; src += 3; + *right++ = littleEndian24Bit (src) << 8; + src += 3; } } } - else if (bitsPerSample == 32) + else { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; - - if (numChannels > 1) + for (int i = 0; i < numThisTime; ++i) { - if (l == 0) + *left++ = littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; + + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = swapIfBigEndian (*src++); - } + ++src; + *r++ = swapIfBigEndian (*src++); } - else if (r == 0) + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *l++ = (swapIfBigEndian (*src++) >> 1) - + (swapIfBigEndian (*src++) >> 1); - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = swapIfBigEndian (*src++); - *r++ = swapIfBigEndian (*src++); - } + *l++ = swapIfBigEndian (*src++); + ++src; } } else @@ -483,66 +450,71 @@ public: for (int i = numThisTime; --i >= 0;) { *l++ = swapIfBigEndian (*src++); + *r++ = swapIfBigEndian (*src++); } } - - left = (int*)l; - right = (int*)r; } - else if (bitsPerSample == 8) + else { - const unsigned char* src = (const unsigned char*) tempBuffer; - - if (numChannels > 1) + for (int i = numThisTime; --i >= 0;) { - if (left == 0) + *l++ = swapIfBigEndian (*src++); + } + } + + left = (int*)l; + right = (int*)r; + } + else if (bitsPerSample == 8) + { + const unsigned char* src = (const unsigned char*) tempBuffer; + + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = ((int) *src++ - 128) << 24; - } + ++src; + *right++ = ((int) *src++ - 128) << 24; } - else if (right == 0) + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - *right++ = ((int) *src++ - 128) << 24; - } + *left++ = ((int) *src++ - 128) << 24; + ++src; } } else { for (int i = numThisTime; --i >= 0;) { - *left++ = ((int)*src++ - 128) << 24; + *left++ = ((int) *src++ - 128) << 24; + *right++ = ((int) *src++ - 128) << 24; } } } - - num -= numThisTime; + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int)*src++ - 128) << 24; + } + } } + + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; } - if (numToDo < numSamples) + if (numSamples > 0) { - int** destChan = destSamples; - - while (*destChan != 0) - { - zeromem ((*destChan) + (startOffsetInDestBuffer + numToDo), - sizeof (int) * (numSamples - numToDo)); - ++destChan; - } + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); } return true; diff --git a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp index 741c4211bc..8b4be67188 100644 --- a/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp +++ b/src/juce_appframework/audio/dsp/juce_AudioSampleBuffer.cpp @@ -626,7 +626,7 @@ void AudioSampleBuffer::readFromAudioReader (AudioFormatReader* reader, chans[2] = 0; - reader->read (chans, readerStartSample, numSamples); + reader->read (chans, 2, readerStartSample, numSamples, true); if (! reader->usesFloatingPointData) {