32template <
typename Type>
39 : channels (static_cast<Type**> (preallocatedChannelSpace))
54 int numSamplesToAllocate)
55 : numChannels (numChannelsToAllocate),
56 size (numSamplesToAllocate)
58 jassert (size >= 0 && numChannels >= 0);
80 : numChannels (numChannelsToUse),
83 jassert (dataToReferTo !=
nullptr);
84 jassert (numChannelsToUse >= 0 && numSamples >= 0);
85 allocateChannels (dataToReferTo, 0);
105 int numChannelsToUse,
108 : numChannels (numChannelsToUse),
111 jassert (dataToReferTo !=
nullptr);
112 jassert (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0);
113 allocateChannels (dataToReferTo, startSample);
123 : numChannels (other.numChannels),
125 allocatedBytes (other.allocatedBytes)
127 if (allocatedBytes == 0)
129 allocateChannels (other.channels, 0);
141 for (
int i = 0; i < numChannels; ++i)
142 FloatVectorOperations::copy (channels[i], other.channels[i], size);
165 for (
int i = 0; i < numChannels; ++i)
166 FloatVectorOperations::copy (channels[i], other.channels[i], size);
181 : numChannels (other.numChannels),
183 allocatedBytes (other.allocatedBytes),
184 allocatedData (std::move (other.allocatedData)),
185 isClear (other.isClear)
189 channels = preallocatedChannelSpace;
191 for (
int i = 0; i < numChannels; ++i)
192 preallocatedChannelSpace[i] = other.channels[i];
196 channels = other.channels;
199 other.numChannels = 0;
201 other.allocatedBytes = 0;
207 numChannels = other.numChannels;
209 allocatedBytes = other.allocatedBytes;
210 allocatedData = std::move (other.allocatedData);
211 isClear = other.isClear;
215 channels = preallocatedChannelSpace;
217 for (
int i = 0; i < numChannels; ++i)
218 preallocatedChannelSpace[i] = other.channels[i];
222 channels = other.channels;
225 other.numChannels = 0;
227 other.allocatedBytes = 0;
256 return channels[channelNumber];
272 return channels[channelNumber] + sampleIndex;
295 return channels[channelNumber];
319 return channels[channelNumber] + sampleIndex;
369 bool keepExistingContent =
false,
370 bool clearExtraSpace =
false,
371 bool avoidReallocating =
false)
376 if (newNumSamples != size || newNumChannels != numChannels)
378 auto allocatedSamplesPerChannel = ((
size_t) newNumSamples + 3) & ~3u;
379 auto channelListSize = ((
static_cast<size_t> (1 + newNumChannels) *
sizeof (Type*)) + 15) & ~15u;
380 auto newTotalBytes = ((
size_t) newNumChannels * (
size_t) allocatedSamplesPerChannel *
sizeof (Type))
381 + channelListSize + 32;
383 if (keepExistingContent)
385 if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
392 newData.
allocate (newTotalBytes, clearExtraSpace || isClear);
394 auto numSamplesToCopy = (
size_t)
jmin (newNumSamples, size);
396 auto newChannels = unalignedPointerCast<Type**> (newData.
get());
397 auto newChan = unalignedPointerCast<Type*> (newData + channelListSize);
399 for (
int j = 0; j < newNumChannels; ++j)
401 newChannels[j] = newChan;
402 newChan += allocatedSamplesPerChannel;
407 auto numChansToCopy =
jmin (numChannels, newNumChannels);
409 for (
int i = 0; i < numChansToCopy; ++i)
410 FloatVectorOperations::copy (newChannels[i], channels[i], (
int) numSamplesToCopy);
414 allocatedBytes = newTotalBytes;
415 channels = newChannels;
420 if (avoidReallocating && allocatedBytes >= newTotalBytes)
422 if (clearExtraSpace || isClear)
423 allocatedData.
clear (newTotalBytes);
427 allocatedBytes = newTotalBytes;
428 allocatedData.
allocate (newTotalBytes, clearExtraSpace || isClear);
429 channels = unalignedPointerCast<Type**> (allocatedData.
get());
432 auto* chan = unalignedPointerCast<Type*> (allocatedData + channelListSize);
434 for (
int i = 0; i < newNumChannels; ++i)
437 chan += allocatedSamplesPerChannel;
441 channels[newNumChannels] =
nullptr;
442 size = newNumSamples;
443 numChannels = newNumChannels;
473 jassert (dataToReferTo !=
nullptr);
474 jassert (newNumChannels >= 0 && newNumSamples >= 0);
476 if (allocatedBytes != 0)
479 allocatedData.
free();
482 numChannels = newNumChannels;
483 size = newNumSamples;
485 allocateChannels (dataToReferTo, newStartSample);
524 template <
typename OtherType>
537 for (
int chan = 0; chan < numChannels; ++chan)
539 auto* dest = channels[chan];
542 for (
int i = 0; i < size; ++i)
543 dest[i] =
static_cast<Type
> (src[i]);
560 for (
int i = 0; i < numChannels; ++i)
562 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)
563 FloatVectorOperations::clear (channels[i], size);
564 JUCE_END_IGNORE_WARNINGS_MSVC
583 void clear (
int startSample,
int numSamples)
noexcept
585 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
589 for (
int i = 0; i < numChannels; ++i)
590 FloatVectorOperations::clear (channels[i] + startSample, numSamples);
592 isClear = (startSample == 0 && numSamples == size);
606 void clear (
int channel,
int startSample,
int numSamples)
noexcept
609 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
612 FloatVectorOperations::clear (channels[channel] + startSample, numSamples);
640 Type
getSample (
int channel,
int sampleIndex)
const noexcept
644 return *(channels[channel] + sampleIndex);
655 void setSample (
int destChannel,
int destSample, Type newValue)
noexcept
659 *(channels[destChannel] + destSample) = newValue;
671 void addSample (
int destChannel,
int destSample, Type valueToAdd)
noexcept
675 *(channels[destChannel] + destSample) += valueToAdd;
684 void applyGain (
int channel,
int startSample,
int numSamples, Type gain)
noexcept
687 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
691 auto* d = channels[channel] + startSample;
694 FloatVectorOperations::clear (d, numSamples);
696 FloatVectorOperations::multiply (d, gain, numSamples);
705 void applyGain (
int startSample,
int numSamples, Type gain)
noexcept
707 for (
int i = 0; i < numChannels; ++i)
708 applyGain (i, startSample, numSamples, gain);
727 Type startGain, Type endGain)
noexcept
733 applyGain (channel, startSample, numSamples, startGain);
738 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
740 const auto increment = (endGain - startGain) / (
float) numSamples;
741 auto* d = channels[channel] + startSample;
743 while (--numSamples >= 0)
746 startGain += increment;
762 Type startGain, Type endGain)
noexcept
764 for (
int i = 0; i < numChannels; ++i)
765 applyGainRamp (i, startSample, numSamples, startGain, endGain);
788 int sourceStartSample,
790 Type gainToApplyToSource = Type (1)) noexcept
793 || sourceChannel != destChannel
794 || sourceStartSample + numSamples <= destStartSample
795 || destStartSample + numSamples <= sourceStartSample);
797 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
799 jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
801 if (!
approximatelyEqual (gainToApplyToSource, (Type) 0) && numSamples > 0 && ! source.isClear)
803 auto* d = channels[destChannel] + destStartSample;
804 auto* s = source.channels[sourceChannel] + sourceStartSample;
806 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)
813 FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
815 FloatVectorOperations::copy (d, s, numSamples);
820 FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples);
822 FloatVectorOperations::add (d, s, numSamples);
825 JUCE_END_IGNORE_WARNINGS_MSVC
847 Type gainToApplyToSource = Type (1)) noexcept
850 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
855 auto* d = channels[destChannel] + destStartSample;
862 FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples);
864 FloatVectorOperations::copy (d, source, numSamples);
869 FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples);
871 FloatVectorOperations::add (d, source, numSamples);
900 Type endGain)
noexcept
904 addFrom (destChannel, destStartSample, source, numSamples, startGain);
909 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
915 const auto increment = (endGain - startGain) / (Type) numSamples;
916 auto* d = channels[destChannel] + destStartSample;
918 while (--numSamples >= 0)
920 *d++ += startGain * *source++;
921 startGain += increment;
942 int sourceStartSample,
943 int numSamples)
noexcept
946 || sourceChannel != destChannel
947 || sourceStartSample + numSamples <= destStartSample
948 || destStartSample + numSamples <= sourceStartSample);
950 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
952 jassert (sourceStartSample >= 0 && numSamples >= 0 && sourceStartSample + numSamples <= source.size);
959 FloatVectorOperations::clear (channels[destChannel] + destStartSample, numSamples);
964 FloatVectorOperations::copy (channels[destChannel] + destStartSample,
965 source.channels[sourceChannel] + sourceStartSample,
986 int numSamples)
noexcept
989 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
995 FloatVectorOperations::copy (channels[destChannel] + destStartSample, source, numSamples);
1013 int destStartSample,
1019 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1024 auto* d = channels[destChannel] + destStartSample;
1031 FloatVectorOperations::clear (d, numSamples);
1036 FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
1042 FloatVectorOperations::copy (d, source, numSamples);
1068 int destStartSample,
1072 Type endGain)
noexcept
1076 copyFrom (destChannel, destStartSample, source, numSamples, startGain);
1081 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1087 const auto increment = (endGain - startGain) / (Type) numSamples;
1088 auto* d = channels[destChannel] + destStartSample;
1090 while (--numSamples >= 0)
1092 *d++ = startGain * *source++;
1093 startGain += increment;
1108 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1111 return { Type (0), Type (0) };
1113 return FloatVectorOperations::findMinAndMax (channels[channel] + startSample, numSamples);
1117 Type
getMagnitude (
int channel,
int startSample,
int numSamples)
const noexcept
1120 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1125 auto r =
findMinMax (channel, startSample, numSamples);
1127 return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1136 for (
int i = 0; i < numChannels; ++i)
1143 Type
getRMSLevel (
int channel,
int startSample,
int numSamples)
const noexcept
1146 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1148 if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1151 auto* data = channels[channel] + startSample;
1154 for (
int i = 0; i < numSamples; ++i)
1156 auto sample = data[i];
1157 sum += sample * sample;
1160 return static_cast<Type
> (
std::sqrt (sum / numSamples));
1164 void reverse (
int channel,
int startSample,
int numSamples)
const noexcept
1167 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1171 channels[channel] + startSample + numSamples);
1175 void reverse (
int startSample,
int numSamples)
const noexcept
1177 for (
int i = 0; i < numChannels; ++i)
1178 reverse (i, startSample, numSamples);
1189 #if (! JUCE_GCC || (__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
1190 static_assert (
alignof (Type) <= maxAlignment,
1191 "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");
1195 auto channelListSize = (
size_t) (numChannels + 1) *
sizeof (Type*);
1197 size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1199 if (alignmentOverflow != 0)
1200 channelListSize += requiredSampleAlignment - alignmentOverflow;
1202 allocatedBytes = (
size_t) numChannels * (
size_t) size *
sizeof (Type) + channelListSize + 32;
1203 allocatedData.
malloc (allocatedBytes);
1204 channels = unalignedPointerCast<Type**> (allocatedData.
get());
1205 auto chan = unalignedPointerCast<Type*> (allocatedData + channelListSize);
1207 for (
int i = 0; i < numChannels; ++i)
1213 channels[numChannels] =
nullptr;
1217 void allocateChannels (Type*
const* dataToReferTo,
int offset)
1224 channels =
static_cast<Type**
> (preallocatedChannelSpace);
1228 allocatedData.
malloc (numChannels + 1,
sizeof (Type*));
1229 channels = unalignedPointerCast<Type**> (allocatedData.
get());
1232 for (
int i = 0; i < numChannels; ++i)
1235 jassert (dataToReferTo[i] !=
nullptr);
1236 channels[i] = dataToReferTo[i] + offset;
1239 channels[numChannels] =
nullptr;
1247 static constexpr size_t getMaxAlignment() noexcept
1254 alignof (
short int),
1257 alignof (
long long int),
1262 alignof (
wchar_t) };
1266 for (
const auto elem : alignments)
1272 int numChannels = 0, size = 0;
1273 size_t allocatedBytes = 0;
1275 HeapBlock<char, true> allocatedData;
1276 Type* preallocatedChannelSpace[32];
1277 bool isClear =
false;
1278 static constexpr size_t maxAlignment = getMaxAlignment();
1284template <
typename Type>
1285bool operator== (
const AudioBuffer<Type>& a,
const AudioBuffer<Type>& b)
1287 if (a.getNumChannels() != b.getNumChannels())
1290 for (
auto c = 0; c < a.getNumChannels(); ++c)
1292 const auto begin = [c] (
auto& x) {
return x.getReadPointer (c); };
1293 const auto end = [c] (
auto& x) {
return x.getReadPointer (c) + x.getNumSamples(); };
1302template <
typename Type>
1303bool operator!= (
const AudioBuffer<Type>& a,
const AudioBuffer<Type>& b)
A multi-channel buffer containing floating point audio samples.
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int startSample, int numSamples)
Creates a buffer using a pre-allocated block of memory.
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
Type getMagnitude(int channel, int startSample, int numSamples) const noexcept
Finds the highest absolute sample value within a region of a channel.
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int numSamples)
Creates a buffer using a pre-allocated block of memory.
Type getSample(int channel, int sampleIndex) const noexcept
Returns a sample from the buffer.
void applyGain(Type gain) noexcept
Applies a gain multiple to all the audio data.
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.
AudioBuffer(const AudioBuffer &other)
Copies another buffer.
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 makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
Resizes this buffer to match the given one, and copies all of its content across.
void setNotClear() noexcept
Forces the internal cleared flag of the buffer to false.
void applyGain(int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of all the channels.
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.
void addSample(int destChannel, int destSample, Type valueToAdd) noexcept
Adds a value to a sample in the buffer.
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
Returns the root mean squared level for a region of a channel.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to 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.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
Type * getWritePointer(int channelNumber, int sampleIndex) noexcept
Returns a writeable pointer to one of the buffer's channels.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
void clear() noexcept
Clears all the samples in all channels and marks the buffer as cleared.
void clear(int channel, int startSample, int numSamples) noexcept
Clears a specified region of just one channel.
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.
~AudioBuffer()=default
Destructor.
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
Copies samples from another buffer to this one.
void reverse(int startSample, int numSamples) const noexcept
Reverses a part of the buffer.
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.
Type getMagnitude(int startSample, int numSamples) const noexcept
Finds the highest absolute sample value within a region on all channels.
void reverse(int channel, int startSample, int numSamples) const noexcept
Reverses a part of a channel.
void setSample(int destChannel, int destSample, Type newValue) noexcept
Sets a sample in the buffer.
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.
bool hasBeenCleared() const noexcept
Returns true if the buffer has been entirely cleared.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
AudioBuffer & operator=(const AudioBuffer &other)
Copies another buffer onto this one.
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
const Type *const * getArrayOfReadPointers() const noexcept
Returns an array of pointers to the channels in the buffer.
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
AudioBuffer(AudioBuffer &&other) noexcept
Move constructor.
Type SampleType
This allows templated code that takes an AudioBuffer to access its sample type.
Type *const * getArrayOfWritePointers() noexcept
Returns an array of pointers to the channels in the buffer.
AudioBuffer() noexcept
Creates an empty buffer with 0 channels and 0 length.
void clear(int startSample, int numSamples) noexcept
Clears a specified region of all the channels.
AudioBuffer(int numChannelsToAllocate, int numSamplesToAllocate)
Creates a buffer with a specified number of channels and samples.
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.
void applyGainRamp(int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of all channels.
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of one channel.
Very simple container class to hold a pointer to some data on the heap.
void clear(SizeType numElements) noexcept
This fills the block with zeros, up to the number of elements specified.
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Swaps this object's data with the data of another HeapBlock.
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
void allocate(SizeType newNumElements, bool initialiseToZero)
Allocates a specified amount of memory and optionally clears it.
void free() noexcept
Frees any currently-allocated data.
A general-purpose range object, that simply represents any linear range with a start and end point.
#define JUCE_LEAK_DETECTOR(OwnerClass)
This macro lets you embed a leak-detecting object inside a class.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Returns the iterator that was passed in.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.