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)
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;
1143using AudioSampleBuffer = AudioBuffer<float>;
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int startSample, int numSamples)
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Type getMagnitude(int channel, int startSample, int numSamples) const noexcept
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int numSamples)
Type getSample(int channel, int sampleIndex) const noexcept
void applyGain(Type gain) noexcept
Range< Type > findMinMax(int channel, int startSample, int numSamples) const noexcept
AudioBuffer(const AudioBuffer &other)
const Type * getReadPointer(int channelNumber, int sampleIndex) const noexcept
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
void applyGain(int startSample, int numSamples, Type gain) noexcept
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newNumSamples)
void copyFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
void addSample(int destChannel, int destSample, Type valueToAdd) noexcept
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
Type * getWritePointer(int channelNumber) noexcept
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples) noexcept
int getNumChannels() const noexcept
Type * getWritePointer(int channelNumber, int sampleIndex) noexcept
int getNumSamples() const noexcept
void clear(int channel, int startSample, int numSamples) 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
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
void reverse(int startSample, int numSamples) const noexcept
void addFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
Type getMagnitude(int startSample, int numSamples) const noexcept
void reverse(int channel, int startSample, int numSamples) const noexcept
void setSample(int destChannel, int destSample, Type newValue) noexcept
void addFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
bool hasBeenCleared() const noexcept
const Type * getReadPointer(int channelNumber) const noexcept
AudioBuffer & operator=(const AudioBuffer &other)
AudioBuffer(AudioBuffer &&other) noexcept
void clear(int startSample, int numSamples) noexcept
const Type ** getArrayOfReadPointers() const noexcept
AudioBuffer(int numChannelsToAllocate, int numSamplesToAllocate)
void addFrom(int destChannel, int destStartSample, const Type *source, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
void applyGainRamp(int startSample, int numSamples, Type startGain, Type endGain) noexcept
Type ** getArrayOfWritePointers() noexcept
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
static void JUCE_CALLTYPE copyWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
static void JUCE_CALLTYPE addWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
static void JUCE_CALLTYPE add(float *dest, float amountToAdd, int numValues) noexcept
void clear(SizeType numElements) noexcept
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
ElementType * get() const noexcept
void allocate(SizeType newNumElements, bool initialiseToZero)