1
0
Fork 0
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:
jules 2019-02-11 17:53:40 +00:00
parent 9d6b393aa9
commit c3245bef0f
2 changed files with 75 additions and 30 deletions

View file

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

View file

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