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:
parent
253e713d02
commit
fc2181aa22
15 changed files with 1192 additions and 1229 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
1154
juce_amalgamated.cpp
1154
juce_amalgamated.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue