From 3d69ce685677e437c7d16d936cb98b5b77701ecb Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 1 Nov 2017 10:24:43 +0000 Subject: [PATCH] Avoided some unnecessary reallocations in AudioBuffer::setSize() --- .../buffers/juce_AudioSampleBuffer.h | 105 +++++++++--------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h b/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h index cfc63ac52b..ffbec42636 100644 --- a/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h +++ b/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h @@ -34,9 +34,7 @@ public: //============================================================================== /** Creates an empty buffer with 0 channels and 0 length. */ AudioBuffer() noexcept - : numChannels (0), size (0), allocatedBytes (0), - channels (static_cast (preallocatedChannelSpace)), - isClear (false) + : channels (static_cast (preallocatedChannelSpace)) { } @@ -78,8 +76,7 @@ public: int numChannelsToUse, int numSamples) : numChannels (numChannelsToUse), - size (numSamples), - allocatedBytes (0) + size (numSamples) { jassert (dataToReferTo != nullptr); jassert (numChannelsToUse >= 0 && numSamples >= 0); @@ -107,9 +104,7 @@ public: int startSample, int numSamples) : numChannels (numChannelsToUse), - size (numSamples), - allocatedBytes (0), - isClear (false) + size (numSamples) { jassert (dataToReferTo != nullptr); jassert (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0); @@ -322,6 +317,9 @@ public: a new allocation will be done so that the buffer uses takes up the minimum amount of memory that it needs. + Note that if keepExistingContent and avoidReallocating are both true, then it will + only avoid reallocating if neither the channel count or length in samples increase. + If the required memory can't be allocated, this will throw a std::bad_alloc exception. */ void setSize (int newNumChannels, @@ -335,38 +333,45 @@ public: if (newNumSamples != size || newNumChannels != numChannels) { - const auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u; - const auto channelListSize = ((sizeof (Type*) * (size_t) (newNumChannels + 1)) + 15) & ~15u; - const auto newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (Type)) - + channelListSize + 32; + auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u; + auto channelListSize = ((sizeof (Type*) * (size_t) (newNumChannels + 1)) + 15) & ~15u; + auto newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (Type)) + + channelListSize + 32; if (keepExistingContent) { - HeapBlock newData; - newData.allocate (newTotalBytes, clearExtraSpace || isClear); - - auto numSamplesToCopy = (size_t) jmin (newNumSamples, size); - - auto newChannels = reinterpret_cast (newData.get()); - auto newChan = reinterpret_cast (newData + channelListSize); - - for (int j = 0; j < newNumChannels; ++j) + if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size) { - newChannels[j] = newChan; - newChan += allocatedSamplesPerChannel; + // no need to do any remapping in this case, as the channel pointers will remain correct! } - - if (! isClear) + else { - auto numChansToCopy = jmin (numChannels, newNumChannels); + HeapBlock newData; + newData.allocate (newTotalBytes, clearExtraSpace || isClear); - for (int i = 0; i < numChansToCopy; ++i) - FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy); + auto numSamplesToCopy = (size_t) jmin (newNumSamples, size); + + auto newChannels = reinterpret_cast (newData.get()); + auto newChan = reinterpret_cast (newData + channelListSize); + + for (int j = 0; j < newNumChannels; ++j) + { + newChannels[j] = newChan; + newChan += allocatedSamplesPerChannel; + } + + if (! isClear) + { + auto numChansToCopy = jmin (numChannels, newNumChannels); + + for (int i = 0; i < numChansToCopy; ++i) + FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy); + } + + allocatedData.swapWith (newData); + allocatedBytes = newTotalBytes; + channels = newChannels; } - - allocatedData.swapWith (newData); - allocatedBytes = newTotalBytes; - channels = newChannels; } else { @@ -391,7 +396,7 @@ public: } } - channels[newNumChannels] = 0; + channels[newNumChannels] = nullptr; size = newNumSamples; numChannels = newNumChannels; } @@ -593,11 +598,11 @@ public: jassert (isPositiveAndBelow (channel, numChannels)); jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size); - if (gain != (Type) 1 && ! isClear) + if (gain != Type (1) && ! isClear) { auto* d = channels[channel] + startSample; - if (gain == 0) + if (gain == Type()) FloatVectorOperations::clear (d, numSamples); else FloatVectorOperations::multiply (d, gain, numSamples); @@ -691,7 +696,7 @@ public: int sourceChannel, int sourceStartSample, int numSamples, - Type gainToApplyToSource = (Type) 1) noexcept + Type gainToApplyToSource = Type (1)) noexcept { jassert (&source != this || sourceChannel != destChannel); jassert (isPositiveAndBelow (destChannel, numChannels)); @@ -708,14 +713,14 @@ public: { isClear = false; - if (gainToApplyToSource != (Type) 1) + if (gainToApplyToSource != Type (1)) FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples); else FloatVectorOperations::copy (d, s, numSamples); } else { - if (gainToApplyToSource != (Type) 1) + if (gainToApplyToSource != Type (1)) FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples); else FloatVectorOperations::add (d, s, numSamples); @@ -723,7 +728,6 @@ public: } } - /** Adds samples from an array of floats to one of the channels. @param destChannel the channel within this buffer to add the samples to @@ -739,7 +743,7 @@ public: int destStartSample, const Type* source, int numSamples, - Type gainToApplyToSource = (Type) 1) noexcept + Type gainToApplyToSource = Type (1)) noexcept { jassert (isPositiveAndBelow (destChannel, numChannels)); jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size); @@ -753,14 +757,14 @@ public: { isClear = false; - if (gainToApplyToSource != (Type) 1) + if (gainToApplyToSource != Type (1)) FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples); else FloatVectorOperations::copy (d, source, numSamples); } else { - if (gainToApplyToSource != (Type) 1) + if (gainToApplyToSource != Type (1)) FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples); else FloatVectorOperations::add (d, source, numSamples); @@ -902,9 +906,9 @@ public: { auto* d = channels[destChannel] + destStartSample; - if (gain != (Type) 1) + if (gain != Type (1)) { - if (gain == 0) + if (gain == Type()) { if (! isClear) FloatVectorOperations::clear (d, numSamples); @@ -1002,7 +1006,7 @@ public: /** Finds the highest absolute sample value within a region on all channels. */ Type getMagnitude (int startSample, int numSamples) const noexcept { - Type mag = 0; + Type mag = {}; if (! isClear) for (int i = 0; i < numChannels; ++i) @@ -1025,11 +1029,11 @@ public: for (int i = 0; i < numSamples; ++i) { - const Type sample = data[i]; + auto sample = data[i]; sum += sample * sample; } - return (Type) std::sqrt (sum / numSamples); + return static_cast (std::sqrt (sum / numSamples)); } /** Reverses a part of a channel. */ @@ -1053,12 +1057,12 @@ public: private: //============================================================================== - int numChannels, size; - size_t allocatedBytes; + int numChannels = 0, size = 0; + size_t allocatedBytes = 0; Type** channels; HeapBlock allocatedData; Type* preallocatedChannelSpace[32]; - bool isClear; + bool isClear = false; void allocateData() { @@ -1098,7 +1102,6 @@ private: { // you have to pass in the same number of valid pointers as numChannels jassert (dataToReferTo[i] != nullptr); - channels[i] = dataToReferTo[i] + offset; }