JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_AudioSampleBuffer.h
Go to the documentation of this file.
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 //==============================================================================
55 : numChannels (numChannelsToAllocate),
57 {
58 jassert (size >= 0 && numChannels >= 0);
59 allocateData();
60 }
61
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
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
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 {
256 return channels[channelNumber];
257 }
258
268 const Type* getReadPointer (int channelNumber, int sampleIndex) const noexcept
269 {
272 return channels[channelNumber] + sampleIndex;
273 }
274
291 Type* getWritePointer (int channelNumber) noexcept
292 {
294 isClear = false;
295 return channels[channelNumber];
296 }
297
314 Type* getWritePointer (int channelNumber, int sampleIndex) noexcept
315 {
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 //==============================================================================
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 {
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
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 {
393
394 auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
395
398
399 for (int j = 0; j < newNumChannels; ++j)
400 {
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;
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
515
524 template <typename OtherType>
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));
644 return *(channels[channel] + sampleIndex);
645 }
646
655 void setSample (int destChannel, int destSample, Type newValue) noexcept
656 {
657 jassert (isPositiveAndBelow (destChannel, numChannels));
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));
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 {
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
785 int destStartSample,
786 const AudioBuffer& source,
787 int sourceChannel,
789 int numSamples,
790 Type gainToApplyToSource = Type (1)) noexcept
791 {
792 jassert (&source != this
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
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
896 int destStartSample,
897 const Type* source,
898 int numSamples,
899 Type startGain,
900 Type endGain) noexcept
901 {
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
939 int destStartSample,
940 const AudioBuffer& source,
941 int sourceChannel,
943 int numSamples) noexcept
944 {
945 jassert (&source != this
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
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
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
1068 int destStartSample,
1069 const Type* source,
1070 int numSamples,
1071 Type startGain,
1072 Type endGain) noexcept
1073 {
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>;
1198
1199 if (alignmentOverflow != 0)
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
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//==============================================================================
1319
1320} // namespace juce
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.
Definition juce_Range.h:40
T equal(T... args)
#define JUCE_LEAK_DETECTOR(OwnerClass)
This macro lets you embed a leak-detecting object inside a class.
#define jassert(expression)
Platform-independent assertion macro.
typedef int
typedef float
T max(T... args)
JUCE Namespace.
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.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
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.
T reverse(T... args)
T sqrt(T... args)
typedef size_t