OpenShot Audio Library | OpenShotAudio  0.6.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 
23 namespace juce
24 {
25 
26 //==============================================================================
32 template <typename Type>
34 {
35 public:
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 
122  AudioBuffer (const AudioBuffer& other)
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 
205  AudioBuffer& operator= (AudioBuffer&& other) noexcept
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 
1185 private:
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 //==============================================================================
1284 template <typename Type>
1285 bool 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 
1302 template <typename Type>
1303 bool operator!= (const AudioBuffer<Type>& a, const AudioBuffer<Type>& b)
1304 {
1305  return ! (a == b);
1306 }
1307 
1308 //==============================================================================
1318 using AudioSampleBuffer = AudioBuffer<float>;
1319 
1320 } // namespace juce
AudioBuffer(Type *const *dataToReferTo, int numChannelsToUse, int startSample, int numSamples)
const Type * getReadPointer(int channelNumber, int sampleIndex) const noexcept
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
Type * getWritePointer(int channelNumber) noexcept
Range< Type > findMinMax(int channel, int startSample, int numSamples) const noexcept
void applyGain(Type gain) noexcept
AudioBuffer(const AudioBuffer &other)
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 * getWritePointer(int channelNumber, int sampleIndex) noexcept
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
void copyFrom(int destChannel, int destStartSample, const Type *source, int numSamples) noexcept
int getNumChannels() const 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
Type *const * getArrayOfWritePointers() 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
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
void setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newNumSamples)
AudioBuffer(AudioBuffer &&other) noexcept
const Type *const * getArrayOfReadPointers() const noexcept
AudioBuffer & operator=(const AudioBuffer &other)
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
const Type * getReadPointer(int channelNumber) const noexcept
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
ElementType * get() const noexcept
void clear(SizeType numElements) noexcept
void swapWith(HeapBlock< ElementType, otherBlockThrows > &other) noexcept
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
void allocate(SizeType newNumElements, bool initialiseToZero)
void free() noexcept