32 template <
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)
164 for (
int i = 0; i < numChannels; ++i)
179 : numChannels (other.numChannels),
181 allocatedBytes (other.allocatedBytes),
182 allocatedData (std::move (other.allocatedData)),
183 isClear (other.isClear.load())
185 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
187 channels = preallocatedChannelSpace;
189 for (
int i = 0; i < numChannels; ++i)
190 preallocatedChannelSpace[i] = other.channels[i];
194 channels = other.channels;
197 other.numChannels = 0;
199 other.allocatedBytes = 0;
205 numChannels = other.numChannels;
207 allocatedBytes = other.allocatedBytes;
208 allocatedData = std::move (other.allocatedData);
209 isClear = other.isClear.load();
211 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
213 channels = preallocatedChannelSpace;
215 for (
int i = 0; i < numChannels; ++i)
216 preallocatedChannelSpace[i] = other.channels[i];
220 channels = other.channels;
223 other.numChannels = 0;
225 other.allocatedBytes = 0;
249 jassert (isPositiveAndBelow (channelNumber, numChannels));
250 return channels[channelNumber];
262 jassert (isPositiveAndBelow (channelNumber, numChannels));
263 jassert (isPositiveAndBelow (sampleIndex, size));
264 return channels[channelNumber] + sampleIndex;
275 jassert (isPositiveAndBelow (channelNumber, numChannels));
277 return channels[channelNumber];
288 jassert (isPositiveAndBelow (channelNumber, numChannels));
289 jassert (isPositiveAndBelow (sampleIndex, size));
291 return channels[channelNumber] + sampleIndex;
333 bool keepExistingContent =
false,
334 bool clearExtraSpace =
false,
335 bool avoidReallocating =
false)
337 jassert (newNumChannels >= 0);
338 jassert (newNumSamples >= 0);
340 if (newNumSamples != size || newNumChannels != numChannels)
342 auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
343 auto channelListSize = ((
static_cast<size_t> (1 + newNumChannels) *
sizeof (Type*)) + 15) & ~15u;
344 auto newTotalBytes = ((size_t) newNumChannels * (
size_t) allocatedSamplesPerChannel *
sizeof (Type))
345 + channelListSize + 32;
347 if (keepExistingContent)
349 if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
356 newData.
allocate (newTotalBytes, clearExtraSpace || isClear);
358 auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
360 auto newChannels =
reinterpret_cast<Type**
> (newData.
get());
361 auto newChan =
reinterpret_cast<Type*
> (newData + channelListSize);
363 for (
int j = 0; j < newNumChannels; ++j)
365 newChannels[j] = newChan;
366 newChan += allocatedSamplesPerChannel;
371 auto numChansToCopy = jmin (numChannels, newNumChannels);
373 for (
int i = 0; i < numChansToCopy; ++i)
378 allocatedBytes = newTotalBytes;
379 channels = newChannels;
384 if (avoidReallocating && allocatedBytes >= newTotalBytes)
386 if (clearExtraSpace || isClear)
387 allocatedData.
clear (newTotalBytes);
391 allocatedBytes = newTotalBytes;
392 allocatedData.
allocate (newTotalBytes, clearExtraSpace || isClear);
393 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
396 auto* chan =
reinterpret_cast<Type*
> (allocatedData + channelListSize);
398 for (
int i = 0; i < newNumChannels; ++i)
401 chan += allocatedSamplesPerChannel;
405 channels[newNumChannels] =
nullptr;
406 size = newNumSamples;
407 numChannels = newNumChannels;
435 jassert (dataToReferTo !=
nullptr);
436 jassert (newNumChannels >= 0 && newNumSamples >= 0);
438 if (allocatedBytes != 0)
441 allocatedData.
free();
444 numChannels = newNumChannels;
445 size = newNumSamples;
447 allocateChannels (dataToReferTo, newStartSample);
480 template <
typename OtherType>
493 for (
int chan = 0; chan < numChannels; ++chan)
495 auto* dest = channels[chan];
498 for (
int i = 0; i < size; ++i)
499 dest[i] = static_cast<Type> (src[i]);
510 for (
int i = 0; i < numChannels; ++i)
522 void clear (
int startSample,
int numSamples) noexcept
524 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
528 if (startSample == 0 && numSamples == size)
531 for (
int i = 0; i < numChannels; ++i)
541 void clear (
int channel,
int startSample,
int numSamples) noexcept
543 jassert (isPositiveAndBelow (channel, numChannels));
544 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
564 Type
getSample (
int channel,
int sampleIndex)
const noexcept
566 jassert (isPositiveAndBelow (channel, numChannels));
567 jassert (isPositiveAndBelow (sampleIndex, size));
568 return *(channels[channel] + sampleIndex);
576 void setSample (
int destChannel,
int destSample, Type newValue) noexcept
578 jassert (isPositiveAndBelow (destChannel, numChannels));
579 jassert (isPositiveAndBelow (destSample, size));
580 *(channels[destChannel] + destSample) = newValue;
589 void addSample (
int destChannel,
int destSample, Type valueToAdd) noexcept
591 jassert (isPositiveAndBelow (destChannel, numChannels));
592 jassert (isPositiveAndBelow (destSample, size));
593 *(channels[destChannel] + destSample) += valueToAdd;
602 void applyGain (
int channel,
int startSample,
int numSamples, Type gain) noexcept
604 jassert (isPositiveAndBelow (channel, numChannels));
605 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
607 if (gain != Type (1) && ! isClear)
609 auto* d = channels[channel] + startSample;
623 void applyGain (
int startSample,
int numSamples, Type gain) noexcept
625 for (
int i = 0; i < numChannels; ++i)
626 applyGain (i, startSample, numSamples, gain);
645 Type startGain, Type endGain) noexcept
649 if (startGain == endGain)
651 applyGain (channel, startSample, numSamples, startGain);
655 jassert (isPositiveAndBelow (channel, numChannels));
656 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
658 const auto increment = (endGain - startGain) / (
float) numSamples;
659 auto* d = channels[channel] + startSample;
661 while (--numSamples >= 0)
664 startGain += increment;
680 Type startGain, Type endGain) noexcept
682 for (
int i = 0; i < numChannels; ++i)
683 applyGainRamp (i, startSample, numSamples, startGain, endGain);
703 int sourceStartSample,
705 Type gainToApplyToSource = Type (1)) noexcept
707 jassert (&source !=
this || sourceChannel != destChannel);
708 jassert (isPositiveAndBelow (destChannel, numChannels));
709 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
710 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
711 jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
713 if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear)
715 auto* d = channels[destChannel] + destStartSample;
716 auto* s = source.channels[sourceChannel] + sourceStartSample;
722 if (gainToApplyToSource != Type (1))
729 if (gainToApplyToSource != Type (1))
752 Type gainToApplyToSource = Type (1)) noexcept
754 jassert (isPositiveAndBelow (destChannel, numChannels));
755 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
756 jassert (source !=
nullptr);
758 if (gainToApplyToSource != 0 && numSamples > 0)
760 auto* d = channels[destChannel] + destStartSample;
766 if (gainToApplyToSource != Type (1))
773 if (gainToApplyToSource != Type (1))
798 Type endGain) noexcept
800 if (startGain == endGain)
802 addFrom (destChannel, destStartSample, source, numSamples, startGain);
806 jassert (isPositiveAndBelow (destChannel, numChannels));
807 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
808 jassert (source !=
nullptr);
813 const auto increment = (endGain - startGain) / numSamples;
814 auto* d = channels[destChannel] + destStartSample;
816 while (--numSamples >= 0)
818 *d++ += startGain * *source++;
819 startGain += increment;
840 int sourceStartSample,
841 int numSamples) noexcept
843 jassert (&source !=
this || sourceChannel != destChannel);
844 jassert (isPositiveAndBelow (destChannel, numChannels));
845 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
846 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
847 jassert (sourceStartSample >= 0 && numSamples >= 0 && sourceStartSample + numSamples <= source.size);
860 source.channels[sourceChannel] + sourceStartSample,
878 int numSamples) noexcept
880 jassert (isPositiveAndBelow (destChannel, numChannels));
881 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
882 jassert (source !=
nullptr);
907 jassert (isPositiveAndBelow (destChannel, numChannels));
908 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
909 jassert (source !=
nullptr);
913 auto* d = channels[destChannel] + destStartSample;
915 if (gain != Type (1))
954 Type endGain) noexcept
956 if (startGain == endGain)
958 copyFrom (destChannel, destStartSample, source, numSamples, startGain);
962 jassert (isPositiveAndBelow (destChannel, numChannels));
963 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
964 jassert (source !=
nullptr);
969 const auto increment = (endGain - startGain) / numSamples;
970 auto* d = channels[destChannel] + destStartSample;
972 while (--numSamples >= 0)
974 *d++ = startGain * *source++;
975 startGain += increment;
989 jassert (isPositiveAndBelow (channel, numChannels));
990 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
993 return { Type (0), Type (0) };
999 Type
getMagnitude (
int channel,
int startSample,
int numSamples)
const noexcept
1001 jassert (isPositiveAndBelow (channel, numChannels));
1002 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1007 auto r =
findMinMax (channel, startSample, numSamples);
1009 return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1018 for (
int i = 0; i < numChannels; ++i)
1019 mag = jmax (mag,
getMagnitude (i, startSample, numSamples));
1025 Type
getRMSLevel (
int channel,
int startSample,
int numSamples)
const noexcept
1027 jassert (isPositiveAndBelow (channel, numChannels));
1028 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1030 if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1033 auto* data = channels[channel] + startSample;
1036 for (
int i = 0; i < numSamples; ++i)
1038 auto sample = data[i];
1039 sum += sample * sample;
1042 return static_cast<Type
> (std::sqrt (sum / numSamples));
1046 void reverse (
int channel,
int startSample,
int numSamples)
const noexcept
1048 jassert (isPositiveAndBelow (channel, numChannels));
1049 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1052 std::reverse (channels[channel] + startSample,
1053 channels[channel] + startSample + numSamples);
1057 void reverse (
int startSample,
int numSamples)
const noexcept
1059 for (
int i = 0; i < numChannels; ++i)
1060 reverse (i, startSample, numSamples);
1069 int numChannels = 0, size = 0;
1070 size_t allocatedBytes = 0;
1073 Type* preallocatedChannelSpace[32];
1074 std::atomic<bool> isClear {
false };
1078 static_assert (std::alignment_of<Type>::value <= std::alignment_of<std::max_align_t>::value,
1079 "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");
1080 jassert (size >= 0);
1082 auto channelListSize = (size_t) (numChannels + 1) *
sizeof (Type*);
1083 auto requiredSampleAlignment = std::alignment_of<Type>::value;
1084 size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1086 if (alignmentOverflow != 0)
1087 channelListSize += requiredSampleAlignment - alignmentOverflow;
1089 allocatedBytes = (size_t) numChannels * (
size_t) size *
sizeof (Type) + channelListSize + 32;
1090 allocatedData.
malloc (allocatedBytes);
1091 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
1092 auto chan =
reinterpret_cast<Type*
> (allocatedData + channelListSize);
1094 for (
int i = 0; i < numChannels; ++i)
1100 channels[numChannels] =
nullptr;
1104 void allocateChannels (Type*
const* dataToReferTo,
int offset)
1106 jassert (offset >= 0);
1109 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
1111 channels =
static_cast<Type**
> (preallocatedChannelSpace);
1115 allocatedData.
malloc (numChannels + 1,
sizeof (Type*));
1116 channels =
reinterpret_cast<Type**
> (allocatedData.
get());
1119 for (
int i = 0; i < numChannels; ++i)
1122 jassert (dataToReferTo[i] !=
nullptr);
1123 channels[i] = dataToReferTo[i] + offset;
1126 channels[numChannels] =
nullptr;
AudioBuffer & operator=(const AudioBuffer &other)
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
void allocate(SizeType newNumElements, bool initialiseToZero)
void addSample(int destChannel, int destSample, Type valueToAdd) noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
static void JUCE_CALLTYPE add(float *dest, float amountToAdd, int numValues) noexcept
void clear(int channel, int startSample, int numSamples) noexcept
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
Type * getWritePointer(int channelNumber, int sampleIndex) noexcept
const Type * getReadPointer(int channelNumber, int sampleIndex) const noexcept
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int startSample, int numSamples)
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newNumSamples)
Type getSample(int channel, int sampleIndex) const noexcept
Type ** getArrayOfWritePointers() noexcept
Range< Type > findMinMax(int channel, int startSample, int numSamples) const noexcept
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
ElementType * get() const noexcept
const Type * getReadPointer(int channelNumber) const noexcept
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples) noexcept
AudioBuffer(AudioBuffer &&other) noexcept
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
void applyGain(Type gain) noexcept
int getNumChannels() const noexcept
AudioBuffer(int numChannelsToAllocate, int numSamplesToAllocate)
void copyFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
void clear(SizeType numElements) noexcept
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples, Type gain) noexcept
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Type getMagnitude(int startSample, int numSamples) const noexcept
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
Type getMagnitude(int channel, int startSample, int numSamples) const noexcept
void addFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
static void JUCE_CALLTYPE copyWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
void clear(int startSample, int numSamples) noexcept
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
static void JUCE_CALLTYPE addWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
void applyGainRamp(int startSample, int numSamples, Type startGain, Type endGain) noexcept
bool hasBeenCleared() const noexcept
void applyGain(int startSample, int numSamples, Type gain) noexcept
Type * getWritePointer(int channelNumber) noexcept
void addFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
void setSample(int destChannel, int destSample, Type newValue) noexcept
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
AudioBuffer(const AudioBuffer &other)
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int numSamples)
int getNumSamples() const noexcept
void addFrom(int destChannel, int destStartSample, const Type *source, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
const Type ** getArrayOfReadPointers() const noexcept
void reverse(int channel, int startSample, int numSamples) const noexcept
void reverse(int startSample, int numSamples) const noexcept