mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added a new AudioFormatReader::read method and refactored the internals a bit
This commit is contained in:
parent
9d6b393aa9
commit
c3245bef0f
2 changed files with 75 additions and 30 deletions
|
|
@ -37,24 +37,45 @@ AudioFormatReader::~AudioFormatReader()
|
|||
delete input;
|
||||
}
|
||||
|
||||
static void convertFixedToFloat (int* const* channels, int numChannels, int numSamples)
|
||||
{
|
||||
for (int i = 0; i < numChannels; ++i)
|
||||
if (auto d = channels[i])
|
||||
FloatVectorOperations::convertFixedToFloat (reinterpret_cast<float*> (d), d, 1.0f / 0x7fffffff, numSamples);
|
||||
}
|
||||
|
||||
bool AudioFormatReader::read (float* const* destChannels, int numDestChannels,
|
||||
int64 startSampleInSource, int numSamplesToRead)
|
||||
{
|
||||
auto channelsAsInt = reinterpret_cast<int* const*> (destChannels);
|
||||
|
||||
if (! read (channelsAsInt, numDestChannels, startSampleInSource, numSamplesToRead, false))
|
||||
return false;
|
||||
|
||||
if (! usesFloatingPointData)
|
||||
convertFixedToFloat (channelsAsInt, numDestChannels, numSamplesToRead);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioFormatReader::read (int* const* destSamples,
|
||||
int numDestChannels,
|
||||
int64 startSampleInSource,
|
||||
int numSamplesToRead,
|
||||
const bool fillLeftoverChannelsWithCopies)
|
||||
bool fillLeftoverChannelsWithCopies)
|
||||
{
|
||||
jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
|
||||
|
||||
const size_t originalNumSamplesToRead = (size_t) numSamplesToRead;
|
||||
auto originalNumSamplesToRead = (size_t) numSamplesToRead;
|
||||
int startOffsetInDestBuffer = 0;
|
||||
|
||||
if (startSampleInSource < 0)
|
||||
{
|
||||
const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
|
||||
auto silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
|
||||
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i], sizeof (int) * (size_t) silence);
|
||||
if (auto d = destSamples[i])
|
||||
zeromem (d, sizeof (int) * (size_t) silence);
|
||||
|
||||
startOffsetInDestBuffer += silence;
|
||||
numSamplesToRead -= silence;
|
||||
|
|
@ -73,7 +94,7 @@ bool AudioFormatReader::read (int* const* destSamples,
|
|||
{
|
||||
if (fillLeftoverChannelsWithCopies)
|
||||
{
|
||||
int* lastFullChannel = destSamples[0];
|
||||
auto lastFullChannel = destSamples[0];
|
||||
|
||||
for (int i = (int) numChannels; --i > 0;)
|
||||
{
|
||||
|
|
@ -86,14 +107,14 @@ bool AudioFormatReader::read (int* const* destSamples,
|
|||
|
||||
if (lastFullChannel != nullptr)
|
||||
for (int i = (int) numChannels; i < numDestChannels; ++i)
|
||||
if (destSamples[i] != nullptr)
|
||||
memcpy (destSamples[i], lastFullChannel, sizeof (int) * originalNumSamplesToRead);
|
||||
if (auto d = destSamples[i])
|
||||
memcpy (d, lastFullChannel, sizeof (int) * originalNumSamplesToRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = (int) numChannels; i < numDestChannels; ++i)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i], sizeof (int) * originalNumSamplesToRead);
|
||||
if (auto d = destSamples[i])
|
||||
zeromem (d, sizeof (int) * originalNumSamplesToRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,13 +122,17 @@ bool AudioFormatReader::read (int* const* destSamples,
|
|||
}
|
||||
|
||||
static void readChannels (AudioFormatReader& reader, int** chans, AudioBuffer<float>* buffer,
|
||||
int startSample, int numSamples, int64 readerStartSample, int numTargetChannels)
|
||||
int startSample, int numSamples, int64 readerStartSample, int numTargetChannels,
|
||||
bool convertToFloat)
|
||||
{
|
||||
for (int j = 0; j < numTargetChannels; ++j)
|
||||
chans[j] = reinterpret_cast<int*> (buffer->getWritePointer (j, startSample));
|
||||
|
||||
chans[numTargetChannels] = nullptr;
|
||||
reader.read (chans, numTargetChannels, readerStartSample, numSamples, true);
|
||||
|
||||
if (convertToFloat)
|
||||
convertFixedToFloat (chans, numTargetChannels, numSamples);
|
||||
}
|
||||
|
||||
void AudioFormatReader::read (AudioBuffer<float>* buffer,
|
||||
|
|
@ -122,52 +147,51 @@ void AudioFormatReader::read (AudioBuffer<float>* buffer,
|
|||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
const int numTargetChannels = buffer->getNumChannels();
|
||||
auto numTargetChannels = buffer->getNumChannels();
|
||||
|
||||
if (numTargetChannels <= 2)
|
||||
{
|
||||
int* const dest0 = reinterpret_cast<int*> (buffer->getWritePointer (0, startSample));
|
||||
int* const dest1 = reinterpret_cast<int*> (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr);
|
||||
int* chans[3];
|
||||
int* dests[2] = { reinterpret_cast<int*> (buffer->getWritePointer (0, startSample)),
|
||||
reinterpret_cast<int*> (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr) };
|
||||
int* chans[3] = {};
|
||||
|
||||
if (useReaderLeftChan == useReaderRightChan)
|
||||
{
|
||||
chans[0] = dest0;
|
||||
chans[1] = numChannels > 1 ? dest1 : nullptr;
|
||||
chans[0] = dests[0];
|
||||
|
||||
if (numChannels > 1)
|
||||
chans[1] = dests[1];
|
||||
}
|
||||
else if (useReaderLeftChan || (numChannels == 1))
|
||||
{
|
||||
chans[0] = dest0;
|
||||
chans[1] = nullptr;
|
||||
chans[0] = dests[0];
|
||||
}
|
||||
else if (useReaderRightChan)
|
||||
{
|
||||
chans[0] = nullptr;
|
||||
chans[1] = dest0;
|
||||
chans[1] = dests[0];
|
||||
}
|
||||
|
||||
chans[2] = nullptr;
|
||||
read (chans, 2, readerStartSample, numSamples, true);
|
||||
|
||||
// if the target's stereo and the source is mono, dupe the first channel..
|
||||
if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr))
|
||||
memcpy (dest1, dest0, sizeof (float) * (size_t) numSamples);
|
||||
memcpy (dests[1], dests[0], sizeof (float) * (size_t) numSamples);
|
||||
|
||||
if (! usesFloatingPointData)
|
||||
convertFixedToFloat (dests, 2, numSamples);
|
||||
}
|
||||
else if (numTargetChannels <= 64)
|
||||
{
|
||||
int* chans[65];
|
||||
readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels);
|
||||
readChannels (*this, chans, buffer, startSample, numSamples,
|
||||
readerStartSample, numTargetChannels, ! usesFloatingPointData);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapBlock<int*> chans (numTargetChannels + 1);
|
||||
readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels);
|
||||
readChannels (*this, chans, buffer, startSample, numSamples,
|
||||
readerStartSample, numTargetChannels, ! usesFloatingPointData);
|
||||
}
|
||||
|
||||
if (! usesFloatingPointData)
|
||||
for (int j = 0; j < numTargetChannels; ++j)
|
||||
if (float* const d = buffer->getWritePointer (j, startSample))
|
||||
FloatVectorOperations::convertFixedToFloat (d, reinterpret_cast<const int*> (d), 1.0f / 0x7fffffff, numSamples);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,27 @@ public:
|
|||
const String& getFormatName() const noexcept { return formatName; }
|
||||
|
||||
//==============================================================================
|
||||
/** Reads samples from the stream.
|
||||
|
||||
@param destSamples an array of float buffers into which the sample data for each
|
||||
channel will be written. Channels that aren't needed can be null
|
||||
@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 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
|
||||
@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
|
||||
*/
|
||||
bool read (float* const* destChannels, int numDestChannels,
|
||||
int64 startSampleInSource, int numSamplesToRead);
|
||||
|
||||
/** Reads samples from the stream.
|
||||
|
||||
@param destSamples an array of buffers into which the sample data for each
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue