1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-02 03:20:06 +00:00

Added a version of AudioFormatReader::readMaxLevels() which takes any number of channels.

This commit is contained in:
jules 2014-08-28 22:02:17 +01:00
parent 5c7bf01c16
commit 7b5b6cbd71
2 changed files with 75 additions and 86 deletions

View file

@ -173,35 +173,54 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer,
}
}
template <typename SampleType>
static Range<SampleType> getChannelMinAndMax (SampleType* channel, int numSamples) noexcept
void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples,
Range<float>* const results, const int channelsToRead)
{
return Range<SampleType>::findMinAndMax (channel, numSamples);
}
jassert (channelsToRead > 0 && channelsToRead <= numChannels);
static Range<float> getChannelMinAndMax (float* channel, int numSamples) noexcept
{
return FloatVectorOperations::findMinAndMax (channel, numSamples);
}
template <typename SampleType>
static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples,
SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax)
{
Range<SampleType> range (getChannelMinAndMax (channels[0], numSamples));
lmax = jmax (lmax, range.getEnd());
lmin = jmin (lmin, range.getStart());
if (numChannels > 1)
if (numSamples <= 0)
{
range = getChannelMinAndMax (channels[1], numSamples);
rmax = jmax (rmax, range.getEnd());
rmin = jmin (rmin, range.getStart());
for (int i = 0; i < channelsToRead; ++i)
results[i] = Range<float>();
return;
}
else
const int bufferSize = (int) jmin (numSamples, (int64) 4096);
AudioSampleBuffer tempSampleBuffer ((int) channelsToRead, bufferSize);
float* const* const floatBuffer = tempSampleBuffer.getArrayOfWritePointers();
int* const* intBuffer = reinterpret_cast<int* const*> (floatBuffer);
bool isFirstBlock = true;
while (numSamples > 0)
{
rmax = lmax;
rmin = lmin;
const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
if (! read (intBuffer, channelsToRead, startSampleInFile, numToDo, false))
break;
for (int i = 0; i < channelsToRead; ++i)
{
Range<float> r;
if (usesFloatingPointData)
{
r = FloatVectorOperations::findMinAndMax (floatBuffer[i], numToDo);
}
else
{
Range<int> intRange (Range<int>::findMinAndMax (intBuffer[i], numToDo));
r = Range<float> (intRange.getStart() / (float) std::numeric_limits<int>::max(),
intRange.getEnd() / (float) std::numeric_limits<int>::max());
}
results[i] = isFirstBlock ? r : results[i].getUnionWith (r);
}
isFirstBlock = false;
numSamples -= numToDo;
startSampleInFile += numToDo;
}
}
@ -209,66 +228,20 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples
float& lowestLeft, float& highestLeft,
float& lowestRight, float& highestRight)
{
if (numSamples <= 0)
Range<float> levels[2];
readMaxLevels (startSampleInFile, numSamples, levels, jmin (2, (int) numChannels));
lowestLeft = levels[0].getStart();
highestLeft = levels[0].getEnd();
if (numChannels > 1)
{
lowestLeft = 0;
lowestRight = 0;
highestLeft = 0;
highestRight = 0;
return;
}
const int bufferSize = (int) jmin (numSamples, (int64) 4096);
AudioSampleBuffer tempSampleBuffer ((int) numChannels, bufferSize);
float* const* const floatBuffer = tempSampleBuffer.getArrayOfWritePointers();
int* const* intBuffer = reinterpret_cast<int* const*> (floatBuffer);
if (usesFloatingPointData)
{
float lmin = 1.0e6f;
float lmax = -lmin;
float rmin = lmin;
float rmax = lmax;
while (numSamples > 0)
{
const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
if (! read (intBuffer, 2, startSampleInFile, numToDo, false))
break;
numSamples -= numToDo;
startSampleInFile += numToDo;
getStereoMinAndMax (floatBuffer, (int) numChannels, numToDo, lmin, lmax, rmin, rmax);
}
lowestLeft = lmin;
highestLeft = lmax;
lowestRight = rmin;
highestRight = rmax;
lowestRight = levels[1].getStart();
highestRight = levels[1].getEnd();
}
else
{
int lmax = std::numeric_limits<int>::min();
int lmin = std::numeric_limits<int>::max();
int rmax = std::numeric_limits<int>::min();
int rmin = std::numeric_limits<int>::max();
while (numSamples > 0)
{
const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
if (! read (intBuffer, 2, startSampleInFile, numToDo, false))
break;
numSamples -= numToDo;
startSampleInFile += numToDo;
getStereoMinAndMax (intBuffer, (int) numChannels, numToDo, lmin, lmax, rmin, rmax);
}
lowestLeft = lmin / (float) std::numeric_limits<int>::max();
highestLeft = lmax / (float) std::numeric_limits<int>::max();
lowestRight = rmin / (float) std::numeric_limits<int>::max();
highestRight = rmax / (float) std::numeric_limits<int>::max();
lowestRight = lowestLeft;
highestRight = highestLeft;
}
}

View file

@ -121,6 +121,25 @@ public:
bool useReaderLeftChan,
bool useReaderRightChan);
/** Finds the highest and lowest sample levels from a section of the audio stream.
This will read a block of samples from the stream, and measure the
highest and lowest sample levels from the channels in that section, returning
these as normalised floating-point levels.
@param startSample the offset into the audio stream to start reading from. It's
ok for this to be beyond the start or end of the stream.
@param numSamples how many samples to read
@param results this array will be filled with Range values for each channel.
The array must contain numChannels elements.
@param numChannelsToRead the number of channels of data to scan. This must be
more than zero, but not more than the total number of channels
that the reader contains
@see read
*/
virtual void readMaxLevels (int64 startSample, int64 numSamples,
Range<float>* results, int numChannelsToRead);
/** Finds the highest and lowest sample levels from a section of the audio stream.
This will read a block of samples from the stream, and measure the
@ -138,12 +157,9 @@ public:
channel (if there is one)
@see read
*/
virtual void readMaxLevels (int64 startSample,
int64 numSamples,
float& lowestLeft,
float& highestLeft,
float& lowestRight,
float& highestRight);
virtual void readMaxLevels (int64 startSample, int64 numSamples,
float& lowestLeft, float& highestLeft,
float& lowestRight, float& highestRight);
/** Scans the source looking for a sample whose magnitude is in a specified range.