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);
155 setSize (other.getNumChannels(), other.getNumSamples(),
false,
false,
false);
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)
187 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
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;
213 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
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;
255 jassert (isPositiveAndBelow (channelNumber, numChannels));
256 return channels[channelNumber];
270 jassert (isPositiveAndBelow (channelNumber, numChannels));
271 jassert (isPositiveAndBelow (sampleIndex, size));
272 return channels[channelNumber] + sampleIndex;
293 jassert (isPositiveAndBelow (channelNumber, numChannels));
295 return channels[channelNumber];
316 jassert (isPositiveAndBelow (channelNumber, numChannels));
317 jassert (isPositiveAndBelow (sampleIndex, size));
319 return channels[channelNumber] + sampleIndex;
369 bool keepExistingContent =
false,
370 bool clearExtraSpace =
false,
371 bool avoidReallocating =
false)
373 jassert (newNumChannels >= 0);
374 jassert (newNumSamples >= 0);
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>
527 setSize (other.getNumChannels(), other.getNumSamples(),
false,
false, avoidReallocating);
529 if (other.hasBeenCleared())
537 for (
int chan = 0; chan < numChannels; ++chan)
539 auto* dest = channels[chan];
540 auto* src = other.getReadPointer (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
608 jassert (isPositiveAndBelow (channel, numChannels));
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
642 jassert (isPositiveAndBelow (channel, numChannels));
643 jassert (isPositiveAndBelow (sampleIndex, size));
644 return *(channels[channel] + sampleIndex);
655 void setSample (
int destChannel,
int destSample, Type newValue)
noexcept
657 jassert (isPositiveAndBelow (destChannel, numChannels));
658 jassert (isPositiveAndBelow (destSample, size));
659 *(channels[destChannel] + destSample) = newValue;
671 void addSample (
int destChannel,
int destSample, Type valueToAdd)
noexcept
673 jassert (isPositiveAndBelow (destChannel, numChannels));
674 jassert (isPositiveAndBelow (destSample, size));
675 *(channels[destChannel] + destSample) += valueToAdd;
684 void applyGain (
int channel,
int startSample,
int numSamples, Type gain)
noexcept
686 jassert (isPositiveAndBelow (channel, numChannels));
687 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
689 if (! approximatelyEqual (gain, Type (1)) && ! isClear)
691 auto* d = channels[channel] + startSample;
693 if (approximatelyEqual (gain, Type()))
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
731 if (approximatelyEqual (startGain, endGain))
733 applyGain (channel, startSample, numSamples, startGain);
737 jassert (isPositiveAndBelow (channel, numChannels));
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
792 jassert (&source !=
this
793 || sourceChannel != destChannel
794 || sourceStartSample + numSamples <= destStartSample
795 || destStartSample + numSamples <= sourceStartSample);
796 jassert (isPositiveAndBelow (destChannel, numChannels));
797 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
798 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
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)
812 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
813 FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
815 FloatVectorOperations::copy (d, s, numSamples);
819 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
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
849 jassert (isPositiveAndBelow (destChannel, numChannels));
850 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
851 jassert (source !=
nullptr);
853 if (! approximatelyEqual (gainToApplyToSource, Type()) && numSamples > 0)
855 auto* d = channels[destChannel] + destStartSample;
861 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
862 FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples);
864 FloatVectorOperations::copy (d, source, numSamples);
868 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
869 FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples);
871 FloatVectorOperations::add (d, source, numSamples);
900 Type endGain)
noexcept
902 if (approximatelyEqual (startGain, endGain))
904 addFrom (destChannel, destStartSample, source, numSamples, startGain);
908 jassert (isPositiveAndBelow (destChannel, numChannels));
909 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
910 jassert (source !=
nullptr);
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
945 jassert (&source !=
this
946 || sourceChannel != destChannel
947 || sourceStartSample + numSamples <= destStartSample
948 || destStartSample + numSamples <= sourceStartSample);
949 jassert (isPositiveAndBelow (destChannel, numChannels));
950 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
951 jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
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
988 jassert (isPositiveAndBelow (destChannel, numChannels));
989 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
990 jassert (source !=
nullptr);
995 FloatVectorOperations::copy (channels[destChannel] + destStartSample, source, numSamples);
1013 int destStartSample,
1018 jassert (isPositiveAndBelow (destChannel, numChannels));
1019 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1020 jassert (source !=
nullptr);
1024 auto* d = channels[destChannel] + destStartSample;
1026 if (! approximatelyEqual (gain, Type (1)))
1028 if (approximatelyEqual (gain, Type()))
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
1074 if (approximatelyEqual (startGain, endGain))
1076 copyFrom (destChannel, destStartSample, source, numSamples, startGain);
1080 jassert (isPositiveAndBelow (destChannel, numChannels));
1081 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1082 jassert (source !=
nullptr);
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;
1107 jassert (isPositiveAndBelow (channel, numChannels));
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
1119 jassert (isPositiveAndBelow (channel, numChannels));
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)
1137 mag = jmax (mag,
getMagnitude (i, startSample, numSamples));
1143 Type
getRMSLevel (
int channel,
int startSample,
int numSamples)
const noexcept
1145 jassert (isPositiveAndBelow (channel, numChannels));
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
1166 jassert (isPositiveAndBelow (channel, numChannels));
1167 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1170 std::reverse (channels[channel] + startSample,
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");
1193 jassert (size >= 0);
1195 auto channelListSize = (size_t) (numChannels + 1) *
sizeof (Type*);
1196 auto requiredSampleAlignment = std::alignment_of_v<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)
1219 jassert (offset >= 0);
1222 if (numChannels < (
int) numElementsInArray (preallocatedChannelSpace))
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
1249 constexpr size_t alignments[] {
alignof (std::max_align_t),
1253 alignof (
long double),
1254 alignof (
short int),
1257 alignof (
long long int),
1262 alignof (
wchar_t) };
1266 for (
const auto elem : alignments)
1267 max = jmax (max, elem);
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(); };
1295 if (! std::equal (begin (a), end (a), begin (b), end (b)))
1302template <
typename Type>
1303bool operator!= (
const AudioBuffer<Type>& a,
const AudioBuffer<Type>& b)
1318using 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 setNotClear() noexcept
void applyGain(int startSample, int numSamples, Type gain) noexcept
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 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)
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
const Type *const * getArrayOfReadPointers() const noexcept
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newNumSamples)
AudioBuffer(AudioBuffer &&other) noexcept
Type *const * getArrayOfWritePointers() noexcept
void clear(int startSample, int numSamples) 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
void applyGain(int channel, int startSample, int numSamples, Type gain) 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)