OpenShot Audio Library | OpenShotAudio 0.4.0
juce_AudioSampleBuffer.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
32template <typename Type>
34{
35public:
36 //==============================================================================
38 AudioBuffer() noexcept
39 : channels (static_cast<Type**> (preallocatedChannelSpace))
40 {
41 }
42
43 //==============================================================================
53 AudioBuffer (int numChannelsToAllocate,
54 int numSamplesToAllocate)
55 : numChannels (numChannelsToAllocate),
56 size (numSamplesToAllocate)
57 {
58 jassert (size >= 0 && numChannels >= 0);
59 allocateData();
60 }
61
77 AudioBuffer (Type* const* dataToReferTo,
78 int numChannelsToUse,
79 int numSamples)
80 : numChannels (numChannelsToUse),
81 size (numSamples)
82 {
83 jassert (dataToReferTo != nullptr);
84 jassert (numChannelsToUse >= 0 && numSamples >= 0);
85 allocateChannels (dataToReferTo, 0);
86 }
87
104 AudioBuffer (Type* const* dataToReferTo,
105 int numChannelsToUse,
106 int startSample,
107 int numSamples)
108 : numChannels (numChannelsToUse),
109 size (numSamples)
110 {
111 jassert (dataToReferTo != nullptr);
112 jassert (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0);
113 allocateChannels (dataToReferTo, startSample);
114 }
115
123 : numChannels (other.numChannels),
124 size (other.size),
125 allocatedBytes (other.allocatedBytes)
126 {
127 if (allocatedBytes == 0)
128 {
129 allocateChannels (other.channels, 0);
130 }
131 else
132 {
133 allocateData();
134
135 if (other.isClear)
136 {
137 clear();
138 }
139 else
140 {
141 for (int i = 0; i < numChannels; ++i)
142 FloatVectorOperations::copy (channels[i], other.channels[i], size);
143 }
144 }
145 }
146
152 {
153 if (this != &other)
154 {
155 setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
156
157 if (other.isClear)
158 {
159 clear();
160 }
161 else
162 {
163 isClear = false;
164
165 for (int i = 0; i < numChannels; ++i)
166 FloatVectorOperations::copy (channels[i], other.channels[i], size);
167 }
168 }
169
170 return *this;
171 }
172
177 ~AudioBuffer() = default;
178
180 AudioBuffer (AudioBuffer&& other) noexcept
181 : numChannels (other.numChannels),
182 size (other.size),
183 allocatedBytes (other.allocatedBytes),
184 allocatedData (std::move (other.allocatedData)),
185 isClear (other.isClear)
186 {
187 if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
188 {
189 channels = preallocatedChannelSpace;
190
191 for (int i = 0; i < numChannels; ++i)
192 preallocatedChannelSpace[i] = other.channels[i];
193 }
194 else
195 {
196 channels = other.channels;
197 }
198
199 other.numChannels = 0;
200 other.size = 0;
201 other.allocatedBytes = 0;
202 }
203
206 {
207 numChannels = other.numChannels;
208 size = other.size;
209 allocatedBytes = other.allocatedBytes;
210 allocatedData = std::move (other.allocatedData);
211 isClear = other.isClear;
212
213 if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
214 {
215 channels = preallocatedChannelSpace;
216
217 for (int i = 0; i < numChannels; ++i)
218 preallocatedChannelSpace[i] = other.channels[i];
219 }
220 else
221 {
222 channels = other.channels;
223 }
224
225 other.numChannels = 0;
226 other.size = 0;
227 other.allocatedBytes = 0;
228 return *this;
229 }
230
231 //==============================================================================
236 int getNumChannels() const noexcept { return numChannels; }
237
242 int getNumSamples() const noexcept { return size; }
243
253 const Type* getReadPointer (int channelNumber) const noexcept
254 {
255 jassert (isPositiveAndBelow (channelNumber, numChannels));
256 return channels[channelNumber];
257 }
258
268 const Type* getReadPointer (int channelNumber, int sampleIndex) const noexcept
269 {
270 jassert (isPositiveAndBelow (channelNumber, numChannels));
271 jassert (isPositiveAndBelow (sampleIndex, size));
272 return channels[channelNumber] + sampleIndex;
273 }
274
291 Type* getWritePointer (int channelNumber) noexcept
292 {
293 jassert (isPositiveAndBelow (channelNumber, numChannels));
294 isClear = false;
295 return channels[channelNumber];
296 }
297
314 Type* getWritePointer (int channelNumber, int sampleIndex) noexcept
315 {
316 jassert (isPositiveAndBelow (channelNumber, numChannels));
317 jassert (isPositiveAndBelow (sampleIndex, size));
318 isClear = false;
319 return channels[channelNumber] + sampleIndex;
320 }
321
327 const Type* const* getArrayOfReadPointers() const noexcept { return channels; }
328
342 Type* const* getArrayOfWritePointers() noexcept { isClear = false; return channels; }
343
344 //==============================================================================
367 void setSize (int newNumChannels,
368 int newNumSamples,
369 bool keepExistingContent = false,
370 bool clearExtraSpace = false,
371 bool avoidReallocating = false)
372 {
373 jassert (newNumChannels >= 0);
374 jassert (newNumSamples >= 0);
375
376 if (newNumSamples != size || newNumChannels != numChannels)
377 {
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;
382
383 if (keepExistingContent)
384 {
385 if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
386 {
387 // no need to do any remapping in this case, as the channel pointers will remain correct!
388 }
389 else
390 {
391 HeapBlock<char, true> newData;
392 newData.allocate (newTotalBytes, clearExtraSpace || isClear);
393
394 auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
395
396 auto newChannels = unalignedPointerCast<Type**> (newData.get());
397 auto newChan = unalignedPointerCast<Type*> (newData + channelListSize);
398
399 for (int j = 0; j < newNumChannels; ++j)
400 {
401 newChannels[j] = newChan;
402 newChan += allocatedSamplesPerChannel;
403 }
404
405 if (! isClear)
406 {
407 auto numChansToCopy = jmin (numChannels, newNumChannels);
408
409 for (int i = 0; i < numChansToCopy; ++i)
410 FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy);
411 }
412
413 allocatedData.swapWith (newData);
414 allocatedBytes = newTotalBytes;
415 channels = newChannels;
416 }
417 }
418 else
419 {
420 if (avoidReallocating && allocatedBytes >= newTotalBytes)
421 {
422 if (clearExtraSpace || isClear)
423 allocatedData.clear (newTotalBytes);
424 }
425 else
426 {
427 allocatedBytes = newTotalBytes;
428 allocatedData.allocate (newTotalBytes, clearExtraSpace || isClear);
429 channels = unalignedPointerCast<Type**> (allocatedData.get());
430 }
431
432 auto* chan = unalignedPointerCast<Type*> (allocatedData + channelListSize);
433
434 for (int i = 0; i < newNumChannels; ++i)
435 {
436 channels[i] = chan;
437 chan += allocatedSamplesPerChannel;
438 }
439 }
440
441 channels[newNumChannels] = nullptr;
442 size = newNumSamples;
443 numChannels = newNumChannels;
444 }
445 }
446
468 void setDataToReferTo (Type* const* dataToReferTo,
469 int newNumChannels,
470 int newStartSample,
471 int newNumSamples)
472 {
473 jassert (dataToReferTo != nullptr);
474 jassert (newNumChannels >= 0 && newNumSamples >= 0);
475
476 if (allocatedBytes != 0)
477 {
478 allocatedBytes = 0;
479 allocatedData.free();
480 }
481
482 numChannels = newNumChannels;
483 size = newNumSamples;
484
485 allocateChannels (dataToReferTo, newStartSample);
486 jassert (! isClear);
487 }
488
509 void setDataToReferTo (Type* const* dataToReferTo,
510 int newNumChannels,
511 int newNumSamples)
512 {
513 setDataToReferTo (dataToReferTo, newNumChannels, 0, newNumSamples);
514 }
515
524 template <typename OtherType>
525 void makeCopyOf (const AudioBuffer<OtherType>& other, bool avoidReallocating = false)
526 {
527 setSize (other.getNumChannels(), other.getNumSamples(), false, false, avoidReallocating);
528
529 if (other.hasBeenCleared())
530 {
531 clear();
532 }
533 else
534 {
535 isClear = false;
536
537 for (int chan = 0; chan < numChannels; ++chan)
538 {
539 auto* dest = channels[chan];
540 auto* src = other.getReadPointer (chan);
541
542 for (int i = 0; i < size; ++i)
543 dest[i] = static_cast<Type> (src[i]);
544 }
545 }
546 }
547
548 //==============================================================================
556 void clear() noexcept
557 {
558 if (! isClear)
559 {
560 for (int i = 0; i < numChannels; ++i)
561 {
562 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)
563 FloatVectorOperations::clear (channels[i], size);
564 JUCE_END_IGNORE_WARNINGS_MSVC
565 }
566
567 isClear = true;
568 }
569 }
570
583 void clear (int startSample, int numSamples) noexcept
584 {
585 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
586
587 if (! isClear)
588 {
589 for (int i = 0; i < numChannels; ++i)
590 FloatVectorOperations::clear (channels[i] + startSample, numSamples);
591
592 isClear = (startSample == 0 && numSamples == size);
593 }
594 }
595
606 void clear (int channel, int startSample, int numSamples) noexcept
607 {
608 jassert (isPositiveAndBelow (channel, numChannels));
609 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
610
611 if (! isClear)
612 FloatVectorOperations::clear (channels[channel] + startSample, numSamples);
613 }
614
622 bool hasBeenCleared() const noexcept { return isClear; }
623
631 void setNotClear() noexcept { isClear = false; }
632
633 //==============================================================================
640 Type getSample (int channel, int sampleIndex) const noexcept
641 {
642 jassert (isPositiveAndBelow (channel, numChannels));
643 jassert (isPositiveAndBelow (sampleIndex, size));
644 return *(channels[channel] + sampleIndex);
645 }
646
655 void setSample (int destChannel, int destSample, Type newValue) noexcept
656 {
657 jassert (isPositiveAndBelow (destChannel, numChannels));
658 jassert (isPositiveAndBelow (destSample, size));
659 *(channels[destChannel] + destSample) = newValue;
660 isClear = false;
661 }
662
671 void addSample (int destChannel, int destSample, Type valueToAdd) noexcept
672 {
673 jassert (isPositiveAndBelow (destChannel, numChannels));
674 jassert (isPositiveAndBelow (destSample, size));
675 *(channels[destChannel] + destSample) += valueToAdd;
676 isClear = false;
677 }
678
684 void applyGain (int channel, int startSample, int numSamples, Type gain) noexcept
685 {
686 jassert (isPositiveAndBelow (channel, numChannels));
687 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
688
689 if (! approximatelyEqual (gain, Type (1)) && ! isClear)
690 {
691 auto* d = channels[channel] + startSample;
692
693 if (approximatelyEqual (gain, Type()))
694 FloatVectorOperations::clear (d, numSamples);
695 else
696 FloatVectorOperations::multiply (d, gain, numSamples);
697 }
698 }
699
705 void applyGain (int startSample, int numSamples, Type gain) noexcept
706 {
707 for (int i = 0; i < numChannels; ++i)
708 applyGain (i, startSample, numSamples, gain);
709 }
710
712 void applyGain (Type gain) noexcept
713 {
714 applyGain (0, size, gain);
715 }
716
726 void applyGainRamp (int channel, int startSample, int numSamples,
727 Type startGain, Type endGain) noexcept
728 {
729 if (! isClear)
730 {
731 if (approximatelyEqual (startGain, endGain))
732 {
733 applyGain (channel, startSample, numSamples, startGain);
734 }
735 else
736 {
737 jassert (isPositiveAndBelow (channel, numChannels));
738 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
739
740 const auto increment = (endGain - startGain) / (float) numSamples;
741 auto* d = channels[channel] + startSample;
742
743 while (--numSamples >= 0)
744 {
745 *d++ *= startGain;
746 startGain += increment;
747 }
748 }
749 }
750 }
751
761 void applyGainRamp (int startSample, int numSamples,
762 Type startGain, Type endGain) noexcept
763 {
764 for (int i = 0; i < numChannels; ++i)
765 applyGainRamp (i, startSample, numSamples, startGain, endGain);
766 }
767
784 void addFrom (int destChannel,
785 int destStartSample,
786 const AudioBuffer& source,
787 int sourceChannel,
788 int sourceStartSample,
789 int numSamples,
790 Type gainToApplyToSource = Type (1)) noexcept
791 {
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);
800
801 if (! approximatelyEqual (gainToApplyToSource, (Type) 0) && numSamples > 0 && ! source.isClear)
802 {
803 auto* d = channels[destChannel] + destStartSample;
804 auto* s = source.channels[sourceChannel] + sourceStartSample;
805
806 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)
807
808 if (isClear)
809 {
810 isClear = false;
811
812 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
813 FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
814 else
815 FloatVectorOperations::copy (d, s, numSamples);
816 }
817 else
818 {
819 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
820 FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples);
821 else
822 FloatVectorOperations::add (d, s, numSamples);
823 }
824
825 JUCE_END_IGNORE_WARNINGS_MSVC
826 }
827 }
828
843 void addFrom (int destChannel,
844 int destStartSample,
845 const Type* source,
846 int numSamples,
847 Type gainToApplyToSource = Type (1)) noexcept
848 {
849 jassert (isPositiveAndBelow (destChannel, numChannels));
850 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
851 jassert (source != nullptr);
852
853 if (! approximatelyEqual (gainToApplyToSource, Type()) && numSamples > 0)
854 {
855 auto* d = channels[destChannel] + destStartSample;
856
857 if (isClear)
858 {
859 isClear = false;
860
861 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
862 FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples);
863 else
864 FloatVectorOperations::copy (d, source, numSamples);
865 }
866 else
867 {
868 if (! approximatelyEqual (gainToApplyToSource, Type (1)))
869 FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples);
870 else
871 FloatVectorOperations::add (d, source, numSamples);
872 }
873 }
874 }
875
876
895 void addFromWithRamp (int destChannel,
896 int destStartSample,
897 const Type* source,
898 int numSamples,
899 Type startGain,
900 Type endGain) noexcept
901 {
902 if (approximatelyEqual (startGain, endGain))
903 {
904 addFrom (destChannel, destStartSample, source, numSamples, startGain);
905 }
906 else
907 {
908 jassert (isPositiveAndBelow (destChannel, numChannels));
909 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
910 jassert (source != nullptr);
911
912 if (numSamples > 0)
913 {
914 isClear = false;
915 const auto increment = (endGain - startGain) / (Type) numSamples;
916 auto* d = channels[destChannel] + destStartSample;
917
918 while (--numSamples >= 0)
919 {
920 *d++ += startGain * *source++;
921 startGain += increment;
922 }
923 }
924 }
925 }
926
938 void copyFrom (int destChannel,
939 int destStartSample,
940 const AudioBuffer& source,
941 int sourceChannel,
942 int sourceStartSample,
943 int numSamples) noexcept
944 {
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);
953
954 if (numSamples > 0)
955 {
956 if (source.isClear)
957 {
958 if (! isClear)
959 FloatVectorOperations::clear (channels[destChannel] + destStartSample, numSamples);
960 }
961 else
962 {
963 isClear = false;
964 FloatVectorOperations::copy (channels[destChannel] + destStartSample,
965 source.channels[sourceChannel] + sourceStartSample,
966 numSamples);
967 }
968 }
969 }
970
983 void copyFrom (int destChannel,
984 int destStartSample,
985 const Type* source,
986 int numSamples) noexcept
987 {
988 jassert (isPositiveAndBelow (destChannel, numChannels));
989 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
990 jassert (source != nullptr);
991
992 if (numSamples > 0)
993 {
994 isClear = false;
995 FloatVectorOperations::copy (channels[destChannel] + destStartSample, source, numSamples);
996 }
997 }
998
1012 void copyFrom (int destChannel,
1013 int destStartSample,
1014 const Type* source,
1015 int numSamples,
1016 Type gain) noexcept
1017 {
1018 jassert (isPositiveAndBelow (destChannel, numChannels));
1019 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1020 jassert (source != nullptr);
1021
1022 if (numSamples > 0)
1023 {
1024 auto* d = channels[destChannel] + destStartSample;
1025
1026 if (! approximatelyEqual (gain, Type (1)))
1027 {
1028 if (approximatelyEqual (gain, Type()))
1029 {
1030 if (! isClear)
1031 FloatVectorOperations::clear (d, numSamples);
1032 }
1033 else
1034 {
1035 isClear = false;
1036 FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
1037 }
1038 }
1039 else
1040 {
1041 isClear = false;
1042 FloatVectorOperations::copy (d, source, numSamples);
1043 }
1044 }
1045 }
1046
1067 void copyFromWithRamp (int destChannel,
1068 int destStartSample,
1069 const Type* source,
1070 int numSamples,
1071 Type startGain,
1072 Type endGain) noexcept
1073 {
1074 if (approximatelyEqual (startGain, endGain))
1075 {
1076 copyFrom (destChannel, destStartSample, source, numSamples, startGain);
1077 }
1078 else
1079 {
1080 jassert (isPositiveAndBelow (destChannel, numChannels));
1081 jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
1082 jassert (source != nullptr);
1083
1084 if (numSamples > 0)
1085 {
1086 isClear = false;
1087 const auto increment = (endGain - startGain) / (Type) numSamples;
1088 auto* d = channels[destChannel] + destStartSample;
1089
1090 while (--numSamples >= 0)
1091 {
1092 *d++ = startGain * *source++;
1093 startGain += increment;
1094 }
1095 }
1096 }
1097 }
1098
1105 Range<Type> findMinMax (int channel, int startSample, int numSamples) const noexcept
1106 {
1107 jassert (isPositiveAndBelow (channel, numChannels));
1108 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1109
1110 if (isClear)
1111 return { Type (0), Type (0) };
1112
1113 return FloatVectorOperations::findMinAndMax (channels[channel] + startSample, numSamples);
1114 }
1115
1117 Type getMagnitude (int channel, int startSample, int numSamples) const noexcept
1118 {
1119 jassert (isPositiveAndBelow (channel, numChannels));
1120 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1121
1122 if (isClear)
1123 return Type (0);
1124
1125 auto r = findMinMax (channel, startSample, numSamples);
1126
1127 return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1128 }
1129
1131 Type getMagnitude (int startSample, int numSamples) const noexcept
1132 {
1133 Type mag (0);
1134
1135 if (! isClear)
1136 for (int i = 0; i < numChannels; ++i)
1137 mag = jmax (mag, getMagnitude (i, startSample, numSamples));
1138
1139 return mag;
1140 }
1141
1143 Type getRMSLevel (int channel, int startSample, int numSamples) const noexcept
1144 {
1145 jassert (isPositiveAndBelow (channel, numChannels));
1146 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1147
1148 if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1149 return Type (0);
1150
1151 auto* data = channels[channel] + startSample;
1152 double sum = 0.0;
1153
1154 for (int i = 0; i < numSamples; ++i)
1155 {
1156 auto sample = data[i];
1157 sum += sample * sample;
1158 }
1159
1160 return static_cast<Type> (std::sqrt (sum / numSamples));
1161 }
1162
1164 void reverse (int channel, int startSample, int numSamples) const noexcept
1165 {
1166 jassert (isPositiveAndBelow (channel, numChannels));
1167 jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1168
1169 if (! isClear)
1170 std::reverse (channels[channel] + startSample,
1171 channels[channel] + startSample + numSamples);
1172 }
1173
1175 void reverse (int startSample, int numSamples) const noexcept
1176 {
1177 for (int i = 0; i < numChannels; ++i)
1178 reverse (i, startSample, numSamples);
1179 }
1180
1181 //==============================================================================
1183 using SampleType = Type;
1184
1185private:
1186 //==============================================================================
1187 void allocateData()
1188 {
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");
1192 #endif
1193 jassert (size >= 0);
1194
1195 auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
1196 auto requiredSampleAlignment = std::alignment_of_v<Type>;
1197 size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1198
1199 if (alignmentOverflow != 0)
1200 channelListSize += requiredSampleAlignment - alignmentOverflow;
1201
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);
1206
1207 for (int i = 0; i < numChannels; ++i)
1208 {
1209 channels[i] = chan;
1210 chan += size;
1211 }
1212
1213 channels[numChannels] = nullptr;
1214 isClear = false;
1215 }
1216
1217 void allocateChannels (Type* const* dataToReferTo, int offset)
1218 {
1219 jassert (offset >= 0);
1220
1221 // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
1222 if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
1223 {
1224 channels = static_cast<Type**> (preallocatedChannelSpace);
1225 }
1226 else
1227 {
1228 allocatedData.malloc (numChannels + 1, sizeof (Type*));
1229 channels = unalignedPointerCast<Type**> (allocatedData.get());
1230 }
1231
1232 for (int i = 0; i < numChannels; ++i)
1233 {
1234 // you have to pass in the same number of valid pointers as numChannels
1235 jassert (dataToReferTo[i] != nullptr);
1236 channels[i] = dataToReferTo[i] + offset;
1237 }
1238
1239 channels[numChannels] = nullptr;
1240 isClear = false;
1241 }
1242
1243 /* On iOS/arm7 the alignment of `double` is greater than the alignment of
1244 `std::max_align_t`, so we can't trust max_align_t. Instead, we query
1245 lots of primitive types and use the maximum alignment of all of them.
1246 */
1247 static constexpr size_t getMaxAlignment() noexcept
1248 {
1249 constexpr size_t alignments[] { alignof (std::max_align_t),
1250 alignof (void*),
1251 alignof (float),
1252 alignof (double),
1253 alignof (long double),
1254 alignof (short int),
1255 alignof (int),
1256 alignof (long int),
1257 alignof (long long int),
1258 alignof (bool),
1259 alignof (char),
1260 alignof (char16_t),
1261 alignof (char32_t),
1262 alignof (wchar_t) };
1263
1264 size_t max = 0;
1265
1266 for (const auto elem : alignments)
1267 max = jmax (max, elem);
1268
1269 return max;
1270 }
1271
1272 int numChannels = 0, size = 0;
1273 size_t allocatedBytes = 0;
1274 Type** channels;
1275 HeapBlock<char, true> allocatedData;
1276 Type* preallocatedChannelSpace[32];
1277 bool isClear = false;
1278 static constexpr size_t maxAlignment = getMaxAlignment();
1279
1280 JUCE_LEAK_DETECTOR (AudioBuffer)
1281};
1282
1283//==============================================================================
1284template <typename Type>
1285bool operator== (const AudioBuffer<Type>& a, const AudioBuffer<Type>& b)
1286{
1287 if (a.getNumChannels() != b.getNumChannels())
1288 return false;
1289
1290 for (auto c = 0; c < a.getNumChannels(); ++c)
1291 {
1292 const auto begin = [c] (auto& x) { return x.getReadPointer (c); };
1293 const auto end = [c] (auto& x) { return x.getReadPointer (c) + x.getNumSamples(); };
1294
1295 if (! std::equal (begin (a), end (a), begin (b), end (b)))
1296 return false;
1297 }
1298
1299 return true;
1300}
1301
1302template <typename Type>
1303bool operator!= (const AudioBuffer<Type>& a, const AudioBuffer<Type>& b)
1304{
1305 return ! (a == b);
1306}
1307
1308//==============================================================================
1318using AudioSampleBuffer = AudioBuffer<float>;
1319
1320} // namespace juce
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
~AudioBuffer()=default
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)
void free() noexcept