1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-15 00:24:19 +00:00

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).

This commit is contained in:
jules 2009-07-02 15:11:45 +00:00
parent 253e713d02
commit fc2181aa22
15 changed files with 1192 additions and 1229 deletions

View file

@ -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)
{

File diff suppressed because it is too large Load diff

View file

@ -3291,8 +3291,8 @@ public:
@see ArrayAllocationBase
*/
OwnedArray (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ObjectClass*> (granularity_),
OwnedArray (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ObjectClass*> (granularity),
numUsed (0)
{
}
@ -4567,8 +4567,8 @@ public:
@see ArrayAllocationBase
*/
Array (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity_),
Array (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity),
numUsed (0)
{
}
@ -10484,8 +10484,8 @@ public:
@see ArrayAllocationBase
*/
SortedSet (const int granularity_ = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (granularity_),
SortedSet (const int granularity = juceDefaultArrayGranularity) throw()
: ArrayAllocationBase <ElementType> (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,

View file

@ -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;

View file

@ -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;

View file

@ -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.
*/

View file

@ -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())

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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)
{