36 template <
typename Type>
43 : channels (static_cast<Type**> (preallocatedChannelSpace))
58 int numSamplesToAllocate)
59 : numChannels (numChannelsToAllocate),
60 size (numSamplesToAllocate)
62 jassert (size >= 0 && numChannels >= 0);
84 : numChannels (numChannelsToUse),
87 jassert (dataToReferTo !=
nullptr);
88 jassert (numChannelsToUse >= 0 && numSamples >= 0);
89 allocateChannels (dataToReferTo, 0);
109 int numChannelsToUse,
112 : numChannels (numChannelsToUse),
115 jassert (dataToReferTo !=
nullptr);
116 jassert (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0);
117 allocateChannels (dataToReferTo, startSample);
127 : numChannels (other.numChannels),
129 allocatedBytes (other.allocatedBytes)
131 if (allocatedBytes == 0)
133 allocateChannels (other.channels, 0);
145 for (
int i = 0; i < numChannels; ++i)
168 for (
int i = 0; i < numChannels; ++i)
183 : numChannels (other.numChannels),
185 allocatedBytes (other.allocatedBytes),
186 allocatedData (std::move (other.allocatedData)),
187 isClear (other.isClear.load())
189 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
191 channels = preallocatedChannelSpace;
193 for (
int i = 0; i < numChannels; ++i)
194 preallocatedChannelSpace[i] = other.channels[i];
198 channels = other.channels;
201 other.numChannels = 0;
203 other.allocatedBytes = 0;
209 numChannels = other.numChannels;
211 allocatedBytes = other.allocatedBytes;
212 allocatedData = std::move (other.allocatedData);
213 isClear = other.isClear.load();
215 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
217 channels = preallocatedChannelSpace;
219 for (
int i = 0; i < numChannels; ++i)
220 preallocatedChannelSpace[i] = other.channels[i];
224 channels = other.channels;
227 other.numChannels = 0;
229 other.allocatedBytes = 0;
253 jassert (isPositiveAndBelow (channelNumber, numChannels));
254 return channels[channelNumber];
266 jassert (isPositiveAndBelow (channelNumber, numChannels));
267 jassert (isPositiveAndBelow (sampleIndex, size));
268 return channels[channelNumber] + sampleIndex;
279 jassert (isPositiveAndBelow (channelNumber, numChannels));
281 return channels[channelNumber];
292 jassert (isPositiveAndBelow (channelNumber, numChannels));
293 jassert (isPositiveAndBelow (sampleIndex, size));
295 return channels[channelNumber] + sampleIndex;
337 bool keepExistingContent =
false,
338 bool clearExtraSpace =
false,
339 bool avoidReallocating =
false)
341 jassert (newNumChannels >= 0);
342 jassert (newNumSamples >= 0);
344 if (newNumSamples != size || newNumChannels != numChannels)
346 auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
347 auto channelListSize = ((
static_cast<size_t> (1 + newNumChannels) *
sizeof (Type*)) + 15) & ~15u;
348 auto newTotalBytes = ((size_t) newNumChannels * (
size_t) allocatedSamplesPerChannel *
sizeof (Type))
349 + channelListSize + 32;
351 if (keepExistingContent)
353 if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
360 newData.
allocate (newTotalBytes, clearExtraSpace || isClear);
362 auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
364 auto newChannels =
reinterpret_cast<Type**
> (newData.
get());
365 auto newChan =
reinterpret_cast<Type*
> (newData + channelListSize);
367 for (
int j = 0; j < newNumChannels; ++j)
369 newChannels[j] = newChan;
370 newChan += allocatedSamplesPerChannel;
375 auto numChansToCopy = jmin (numChannels, newNumChannels);
377 for (
int i = 0; i < numChansToCopy; ++i)
382 allocatedBytes = newTotalBytes;
383 channels = newChannels;
388 if (avoidReallocating && allocatedBytes >= newTotalBytes)
390 if (clearExtraSpace || isClear)
391 allocatedData.
clear (newTotalBytes);
395 allocatedBytes = newTotalBytes;
396 allocatedData.
allocate (newTotalBytes, clearExtraSpace || isClear);
397 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
400 auto* chan =
reinterpret_cast<Type*
> (allocatedData + channelListSize);
402 for (
int i = 0; i < newNumChannels; ++i)
405 chan += allocatedSamplesPerChannel;
409 channels[newNumChannels] =
nullptr;
410 size = newNumSamples;
411 numChannels = newNumChannels;
439 jassert (dataToReferTo !=
nullptr);
440 jassert (newNumChannels >= 0 && newNumSamples >= 0);
442 if (allocatedBytes != 0)
445 allocatedData.
free();
448 numChannels = newNumChannels;
449 size = newNumSamples;
451 allocateChannels (dataToReferTo, newStartSample);
484 template <
typename OtherType>
497 for (
int chan = 0; chan < numChannels; ++chan)
499 auto* dest = channels[chan];
502 for (
int i = 0; i < size; ++i)
503 dest[i] = static_cast<Type> (src[i]);
514 for (
int i = 0; i < numChannels; ++i)
526 void clear (
int startSample,
int numSamples) noexcept
528 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
532 if (startSample == 0 && numSamples == size)
535 for (
int i = 0; i < numChannels; ++i)
545 void clear (
int channel,
int startSample,
int numSamples) noexcept
547 jassert (isPositiveAndBelow (channel, numChannels));
548 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
568 Type
getSample (
int channel,
int sampleIndex)
const noexcept
570 jassert (isPositiveAndBelow (channel, numChannels));
571 jassert (isPositiveAndBelow (sampleIndex, size));
572 return *(channels[channel] + sampleIndex);
580 void setSample (
int destChannel,
int destSample, Type newValue) noexcept
582 jassert (isPositiveAndBelow (destChannel, numChannels));
583 jassert (isPositiveAndBelow (destSample, size));
584 *(channels[destChannel] + destSample) = newValue;
593 void addSample (
int destChannel,
int destSample, Type valueToAdd) noexcept
595 jassert (isPositiveAndBelow (destChannel, numChannels));
596 jassert (isPositiveAndBelow (destSample, size));
597 *(channels[destChannel] + destSample) += valueToAdd;
606 void applyGain (
int channel,
int startSample,
int numSamples, Type gain) noexcept
608 jassert (isPositiveAndBelow (channel, numChannels));
609 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
611 if (gain != Type (1) && ! isClear)
613 auto* d = channels[channel] + startSample;
627 void applyGain (
int startSample,
int numSamples, Type gain) noexcept
629 for (
int i = 0; i < numChannels; ++i)
630 applyGain (i, startSample, numSamples, gain);
649 Type startGain, Type endGain) noexcept
653 if (startGain == endGain)
655 applyGain (channel, startSample, numSamples, startGain);
659 jassert (isPositiveAndBelow (channel, numChannels));
660 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
662 const auto increment = (endGain - startGain) / (
float) numSamples;
663 auto* d = channels[channel] + startSample;
665 while (--numSamples >= 0)
668 startGain += increment;
684 Type startGain, Type endGain) noexcept
686 for (
int i = 0; i < numChannels; ++i)
687 applyGainRamp (i, startSample, numSamples, startGain, endGain);
707 int sourceStartSample,
709 Type gainToApplyToSource = Type (1)) noexcept
711 jassert (&source !=
this || sourceChannel != destChannel);
712 jassert (isPositiveAndBelow (destChannel, numChannels));
713 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
714 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
715 jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
717 if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear)
719 auto* d = channels[destChannel] + destStartSample;
720 auto* s = source.channels[sourceChannel] + sourceStartSample;
726 if (gainToApplyToSource != Type (1))
733 if (gainToApplyToSource != Type (1))
756 Type gainToApplyToSource = Type (1)) noexcept
758 jassert (isPositiveAndBelow (destChannel, numChannels));
759 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
760 jassert (source !=
nullptr);
762 if (gainToApplyToSource != 0 && numSamples > 0)
764 auto* d = channels[destChannel] + destStartSample;
770 if (gainToApplyToSource != Type (1))
777 if (gainToApplyToSource != Type (1))
802 Type endGain) noexcept
804 if (startGain == endGain)
806 addFrom (destChannel, destStartSample, source, numSamples, startGain);
810 jassert (isPositiveAndBelow (destChannel, numChannels));
811 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
812 jassert (source !=
nullptr);
817 const auto increment = (endGain - startGain) / numSamples;
818 auto* d = channels[destChannel] + destStartSample;
820 while (--numSamples >= 0)
822 *d++ += startGain * *source++;
823 startGain += increment;
844 int sourceStartSample,
845 int numSamples) noexcept
847 jassert (&source !=
this || sourceChannel != destChannel);
848 jassert (isPositiveAndBelow (destChannel, numChannels));
849 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
850 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
851 jassert (sourceStartSample >= 0 && numSamples >= 0 && sourceStartSample + numSamples <= source.size);
864 source.channels[sourceChannel] + sourceStartSample,
882 int numSamples) noexcept
884 jassert (isPositiveAndBelow (destChannel, numChannels));
885 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
886 jassert (source !=
nullptr);
911 jassert (isPositiveAndBelow (destChannel, numChannels));
912 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
913 jassert (source !=
nullptr);
917 auto* d = channels[destChannel] + destStartSample;
919 if (gain != Type (1))
958 Type endGain) noexcept
960 if (startGain == endGain)
962 copyFrom (destChannel, destStartSample, source, numSamples, startGain);
966 jassert (isPositiveAndBelow (destChannel, numChannels));
967 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
968 jassert (source !=
nullptr);
973 const auto increment = (endGain - startGain) / numSamples;
974 auto* d = channels[destChannel] + destStartSample;
976 while (--numSamples >= 0)
978 *d++ = startGain * *source++;
979 startGain += increment;
993 jassert (isPositiveAndBelow (channel, numChannels));
994 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
997 return { Type (0), Type (0) };
1003 Type
getMagnitude (
int channel,
int startSample,
int numSamples)
const noexcept
1005 jassert (isPositiveAndBelow (channel, numChannels));
1006 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1011 auto r =
findMinMax (channel, startSample, numSamples);
1013 return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1022 for (
int i = 0; i < numChannels; ++i)
1023 mag = jmax (mag,
getMagnitude (i, startSample, numSamples));
1029 Type
getRMSLevel (
int channel,
int startSample,
int numSamples)
const noexcept
1031 jassert (isPositiveAndBelow (channel, numChannels));
1032 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1034 if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1037 auto* data = channels[channel] + startSample;
1040 for (
int i = 0; i < numSamples; ++i)
1042 auto sample = data[i];
1043 sum += sample * sample;
1046 return static_cast<Type
> (std::sqrt (sum / numSamples));
1050 void reverse (
int channel,
int startSample,
int numSamples)
const noexcept
1052 jassert (isPositiveAndBelow (channel, numChannels));
1053 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1056 std::reverse (channels[channel] + startSample,
1057 channels[channel] + startSample + numSamples);
1061 void reverse (
int startSample,
int numSamples)
const noexcept
1063 for (
int i = 0; i < numChannels; ++i)
1064 reverse (i, startSample, numSamples);
1073 int numChannels = 0, size = 0;
1074 size_t allocatedBytes = 0;
1077 Type* preallocatedChannelSpace[32];
1078 std::atomic<bool> isClear {
false };
1082 static_assert (std::alignment_of<Type>::value <= std::alignment_of<std::max_align_t>::value,
1083 "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");
1084 jassert (size >= 0);
1086 auto channelListSize = (size_t) (numChannels + 1) *
sizeof (Type*);
1087 auto requiredSampleAlignment = std::alignment_of<Type>::value;
1088 size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1090 if (alignmentOverflow != 0)
1091 channelListSize += requiredSampleAlignment - alignmentOverflow;
1093 allocatedBytes = (size_t) numChannels * (
size_t) size *
sizeof (Type) + channelListSize + 32;
1094 allocatedData.
malloc (allocatedBytes);
1095 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
1096 auto chan =
reinterpret_cast<Type*
> (allocatedData + channelListSize);
1098 for (
int i = 0; i < numChannels; ++i)
1104 channels[numChannels] =
nullptr;
1108 void allocateChannels (Type*
const* dataToReferTo,
int offset)
1110 jassert (offset >= 0);
1113 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
1115 channels =
static_cast<Type**
> (preallocatedChannelSpace);
1119 allocatedData.
malloc (numChannels + 1,
sizeof (Type*));
1120 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
1123 for (
int i = 0; i < numChannels; ++i)
1126 jassert (dataToReferTo[i] !=
nullptr);
1127 channels[i] = dataToReferTo[i] + offset;
1130 channels[numChannels] =
nullptr;
AudioBuffer & operator=(const AudioBuffer &other)
Copies another buffer onto this one.
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
Returns the root mean squared level for a region of a channel.
void allocate(SizeType newNumElements, bool initialiseToZero)
Allocates a specified amount of memory and optionally clears it.
void addSample(int destChannel, int destSample, Type valueToAdd) noexcept
Adds a value to a sample in the buffer.
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
static void JUCE_CALLTYPE add(float *dest, float amountToAdd, int numValues) noexcept
Adds a fixed value to the destination values.
void clear(int channel, int startSample, int numSamples) noexcept
Clears a specified region of just one channel.
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
Copies a vector of floats.
Type * getWritePointer(int channelNumber, int sampleIndex) noexcept
Returns a writeable pointer to one of the buffer's channels.
const Type * getReadPointer(int channelNumber, int sampleIndex) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int startSample, int numSamples)
Creates a buffer using a pre-allocated block of memory.
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
Type getSample(int channel, int sampleIndex) const noexcept
Returns a sample from the buffer.
Type ** getArrayOfWritePointers() noexcept
Returns an array of pointers to the channels in the buffer.
Range< Type > findMinMax(int channel, int startSample, int numSamples) const noexcept
Returns a Range indicating the lowest and highest sample values in a given section.
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
Multiplies the destination values by the source values.
AudioBuffer() noexcept
Creates an empty buffer with 0 channels and 0 length.
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples) noexcept
Copies samples from an array of floats into one of the channels.
A multi-channel buffer containing floating point audio samples.
AudioBuffer(AudioBuffer &&other) noexcept
Move constructor.
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of one channel.
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
Finds the minimum and maximum values in the given array.
void applyGain(Type gain) noexcept
Applies a gain multiple to all the audio data.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
AudioBuffer(int numChannelsToAllocate, int numSamplesToAllocate)
Creates a buffer with a specified number of channels and samples.
void copyFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
Copies samples from an array of floats into one of the channels, applying a gain ramp.
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
Clears a vector of floats.
void clear(SizeType numElements) noexcept
This fills the block with zeros, up to the number of elements specified.
void free() noexcept
Frees any currently-allocated data.
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples, Type gain) noexcept
Copies samples from an array of floats into one of the channels, applying a gain to it...
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
Type getMagnitude(int startSample, int numSamples) const noexcept
Finds the highest absolute sample value within a region on all channels.
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Swaps this object's data with the data of another HeapBlock.
Type getMagnitude(int channel, int startSample, int numSamples) const noexcept
Finds the highest absolute sample value within a region of a channel.
void addFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
Adds samples from another buffer to this one.
static void JUCE_CALLTYPE copyWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
Copies a vector of floats, multiplying each value by a given multiplier.
void clear(int startSample, int numSamples) noexcept
Clears a specified region of all the channels.
~AudioBuffer()=default
Destructor.
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
Resizes this buffer to match the given one, and copies all of its content across. ...
static void JUCE_CALLTYPE addWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
Multiplies each source value by the given multiplier, then adds it to the destination value...
void applyGainRamp(int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of all channels.
bool hasBeenCleared() const noexcept
Returns true if the buffer has been entirely cleared.
void applyGain(int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of all the channels.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
void addFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
Adds samples from an array of floats, applying a gain ramp to them.
void setSample(int destChannel, int destSample, Type newValue) noexcept
Sets a sample in the buffer.
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
Copies samples from another buffer to this one.
AudioBuffer(const AudioBuffer &other)
Copies another buffer.
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int numSamples)
Creates a buffer using a pre-allocated block of memory.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
void addFrom(int destChannel, int destStartSample, const Type *source, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
Adds samples from an array of floats to one of the channels.
float SampleType
This allows templated code that takes an AudioBuffer to access its sample type.
const Type ** getArrayOfReadPointers() const noexcept
Returns an array of pointers to the channels in the buffer.
void reverse(int channel, int startSample, int numSamples) const noexcept
Reverses a part of a channel.
void reverse(int startSample, int numSamples) const noexcept
Reverses a part of the buffer.
void clear() noexcept
Clears all the samples in all channels.