OpenShot Audio Library | OpenShotAudio  0.3.3
juce_AudioSampleBuffer.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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 
151  {
152  if (this != &other)
153  {
154  setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
155 
156  if (other.isClear)
157  {
158  clear();
159  }
160  else
161  {
162  isClear = false;
163 
164  for (int i = 0; i < numChannels; ++i)
165  FloatVectorOperations::copy (channels[i], other.channels[i], size);
166  }
167  }
168 
169  return *this;
170  }
171 
175  ~AudioBuffer() = default;
176 
178  AudioBuffer (AudioBuffer&& other) noexcept
179  : numChannels (other.numChannels),
180  size (other.size),
181  allocatedBytes (other.allocatedBytes),
182  allocatedData (std::move (other.allocatedData)),
183  isClear (other.isClear.load())
184  {
185  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
186  {
187  channels = preallocatedChannelSpace;
188 
189  for (int i = 0; i < numChannels; ++i)
190  preallocatedChannelSpace[i] = other.channels[i];
191  }
192  else
193  {
194  channels = other.channels;
195  }
196 
197  other.numChannels = 0;
198  other.size = 0;
199  other.allocatedBytes = 0;
200  }
201 
203  AudioBuffer& operator= (AudioBuffer&& other) noexcept
204  {
205  numChannels = other.numChannels;
206  size = other.size;
207  allocatedBytes = other.allocatedBytes;
208  allocatedData = std::move (other.allocatedData);
209  isClear = other.isClear.load();
210 
211  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
212  {
213  channels = preallocatedChannelSpace;
214 
215  for (int i = 0; i < numChannels; ++i)
216  preallocatedChannelSpace[i] = other.channels[i];
217  }
218  else
219  {
220  channels = other.channels;
221  }
222 
223  other.numChannels = 0;
224  other.size = 0;
225  other.allocatedBytes = 0;
226  return *this;
227  }
228 
229  //==============================================================================
233  int getNumChannels() const noexcept { return numChannels; }
234 
238  int getNumSamples() const noexcept { return size; }
239 
247  const Type* getReadPointer (int channelNumber) const noexcept
248  {
249  jassert (isPositiveAndBelow (channelNumber, numChannels));
250  return channels[channelNumber];
251  }
252 
260  const Type* getReadPointer (int channelNumber, int sampleIndex) const noexcept
261  {
262  jassert (isPositiveAndBelow (channelNumber, numChannels));
263  jassert (isPositiveAndBelow (sampleIndex, size));
264  return channels[channelNumber] + sampleIndex;
265  }
266 
273  Type* getWritePointer (int channelNumber) noexcept
274  {
275  jassert (isPositiveAndBelow (channelNumber, numChannels));
276  isClear = false;
277  return channels[channelNumber];
278  }
279 
286  Type* getWritePointer (int channelNumber, int sampleIndex) noexcept
287  {
288  jassert (isPositiveAndBelow (channelNumber, numChannels));
289  jassert (isPositiveAndBelow (sampleIndex, size));
290  isClear = false;
291  return channels[channelNumber] + sampleIndex;
292  }
293 
299  const Type** getArrayOfReadPointers() const noexcept { return const_cast<const Type**> (channels); }
300 
306  Type** getArrayOfWritePointers() noexcept { isClear = false; return channels; }
307 
308  //==============================================================================
331  void setSize (int newNumChannels,
332  int newNumSamples,
333  bool keepExistingContent = false,
334  bool clearExtraSpace = false,
335  bool avoidReallocating = false)
336  {
337  jassert (newNumChannels >= 0);
338  jassert (newNumSamples >= 0);
339 
340  if (newNumSamples != size || newNumChannels != numChannels)
341  {
342  auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
343  auto channelListSize = ((static_cast<size_t> (1 + newNumChannels) * sizeof (Type*)) + 15) & ~15u;
344  auto newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (Type))
345  + channelListSize + 32;
346 
347  if (keepExistingContent)
348  {
349  if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
350  {
351  // no need to do any remapping in this case, as the channel pointers will remain correct!
352  }
353  else
354  {
355  HeapBlock<char, true> newData;
356  newData.allocate (newTotalBytes, clearExtraSpace || isClear);
357 
358  auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
359 
360  auto newChannels = reinterpret_cast<Type**> (newData.get());
361  auto newChan = reinterpret_cast<Type*> (newData + channelListSize);
362 
363  for (int j = 0; j < newNumChannels; ++j)
364  {
365  newChannels[j] = newChan;
366  newChan += allocatedSamplesPerChannel;
367  }
368 
369  if (! isClear)
370  {
371  auto numChansToCopy = jmin (numChannels, newNumChannels);
372 
373  for (int i = 0; i < numChansToCopy; ++i)
374  FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy);
375  }
376 
377  allocatedData.swapWith (newData);
378  allocatedBytes = newTotalBytes;
379  channels = newChannels;
380  }
381  }
382  else
383  {
384  if (avoidReallocating && allocatedBytes >= newTotalBytes)
385  {
386  if (clearExtraSpace || isClear)
387  allocatedData.clear (newTotalBytes);
388  }
389  else
390  {
391  allocatedBytes = newTotalBytes;
392  allocatedData.allocate (newTotalBytes, clearExtraSpace || isClear);
393  channels = reinterpret_cast<Type**> (allocatedData.get());
394  }
395 
396  auto* chan = reinterpret_cast<Type*> (allocatedData + channelListSize);
397 
398  for (int i = 0; i < newNumChannels; ++i)
399  {
400  channels[i] = chan;
401  chan += allocatedSamplesPerChannel;
402  }
403  }
404 
405  channels[newNumChannels] = nullptr;
406  size = newNumSamples;
407  numChannels = newNumChannels;
408  }
409  }
410 
430  void setDataToReferTo (Type** dataToReferTo,
431  int newNumChannels,
432  int newStartSample,
433  int newNumSamples)
434  {
435  jassert (dataToReferTo != nullptr);
436  jassert (newNumChannels >= 0 && newNumSamples >= 0);
437 
438  if (allocatedBytes != 0)
439  {
440  allocatedBytes = 0;
441  allocatedData.free();
442  }
443 
444  numChannels = newNumChannels;
445  size = newNumSamples;
446 
447  allocateChannels (dataToReferTo, newStartSample);
448  jassert (! isClear);
449  }
450 
469  void setDataToReferTo (Type** dataToReferTo,
470  int newNumChannels,
471  int newNumSamples)
472  {
473  setDataToReferTo (dataToReferTo, newNumChannels, 0, newNumSamples);
474  }
475 
480  template <typename OtherType>
481  void makeCopyOf (const AudioBuffer<OtherType>& other, bool avoidReallocating = false)
482  {
483  setSize (other.getNumChannels(), other.getNumSamples(), false, false, avoidReallocating);
484 
485  if (other.hasBeenCleared())
486  {
487  clear();
488  }
489  else
490  {
491  isClear = false;
492 
493  for (int chan = 0; chan < numChannels; ++chan)
494  {
495  auto* dest = channels[chan];
496  auto* src = other.getReadPointer (chan);
497 
498  for (int i = 0; i < size; ++i)
499  dest[i] = static_cast<Type> (src[i]);
500  }
501  }
502  }
503 
504  //==============================================================================
506  void clear() noexcept
507  {
508  if (! isClear)
509  {
510  for (int i = 0; i < numChannels; ++i)
511  FloatVectorOperations::clear (channels[i], size);
512 
513  isClear = true;
514  }
515  }
516 
522  void clear (int startSample, int numSamples) noexcept
523  {
524  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
525 
526  if (! isClear)
527  {
528  if (startSample == 0 && numSamples == size)
529  isClear = true;
530 
531  for (int i = 0; i < numChannels; ++i)
532  FloatVectorOperations::clear (channels[i] + startSample, numSamples);
533  }
534  }
535 
541  void clear (int channel, int startSample, int numSamples) noexcept
542  {
543  jassert (isPositiveAndBelow (channel, numChannels));
544  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
545 
546  if (! isClear)
547  FloatVectorOperations::clear (channels[channel] + startSample, numSamples);
548  }
549 
556  bool hasBeenCleared() const noexcept { return isClear; }
557 
558  //==============================================================================
564  Type getSample (int channel, int sampleIndex) const noexcept
565  {
566  jassert (isPositiveAndBelow (channel, numChannels));
567  jassert (isPositiveAndBelow (sampleIndex, size));
568  return *(channels[channel] + sampleIndex);
569  }
570 
576  void setSample (int destChannel, int destSample, Type newValue) noexcept
577  {
578  jassert (isPositiveAndBelow (destChannel, numChannels));
579  jassert (isPositiveAndBelow (destSample, size));
580  *(channels[destChannel] + destSample) = newValue;
581  isClear = false;
582  }
583 
589  void addSample (int destChannel, int destSample, Type valueToAdd) noexcept
590  {
591  jassert (isPositiveAndBelow (destChannel, numChannels));
592  jassert (isPositiveAndBelow (destSample, size));
593  *(channels[destChannel] + destSample) += valueToAdd;
594  isClear = false;
595  }
596 
602  void applyGain (int channel, int startSample, int numSamples, Type gain) noexcept
603  {
604  jassert (isPositiveAndBelow (channel, numChannels));
605  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
606 
607  if (gain != Type (1) && ! isClear)
608  {
609  auto* d = channels[channel] + startSample;
610 
611  if (gain == Type())
612  FloatVectorOperations::clear (d, numSamples);
613  else
614  FloatVectorOperations::multiply (d, gain, numSamples);
615  }
616  }
617 
623  void applyGain (int startSample, int numSamples, Type gain) noexcept
624  {
625  for (int i = 0; i < numChannels; ++i)
626  applyGain (i, startSample, numSamples, gain);
627  }
628 
630  void applyGain (Type gain) noexcept
631  {
632  applyGain (0, size, gain);
633  }
634 
644  void applyGainRamp (int channel, int startSample, int numSamples,
645  Type startGain, Type endGain) noexcept
646  {
647  if (! isClear)
648  {
649  if (startGain == endGain)
650  {
651  applyGain (channel, startSample, numSamples, startGain);
652  }
653  else
654  {
655  jassert (isPositiveAndBelow (channel, numChannels));
656  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
657 
658  const auto increment = (endGain - startGain) / (float) numSamples;
659  auto* d = channels[channel] + startSample;
660 
661  while (--numSamples >= 0)
662  {
663  *d++ *= startGain;
664  startGain += increment;
665  }
666  }
667  }
668  }
669 
679  void applyGainRamp (int startSample, int numSamples,
680  Type startGain, Type endGain) noexcept
681  {
682  for (int i = 0; i < numChannels; ++i)
683  applyGainRamp (i, startSample, numSamples, startGain, endGain);
684  }
685 
699  void addFrom (int destChannel,
700  int destStartSample,
701  const AudioBuffer& source,
702  int sourceChannel,
703  int sourceStartSample,
704  int numSamples,
705  Type gainToApplyToSource = Type (1)) noexcept
706  {
707  jassert (&source != this || sourceChannel != destChannel);
708  jassert (isPositiveAndBelow (destChannel, numChannels));
709  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
710  jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
711  jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
712 
713  if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear)
714  {
715  auto* d = channels[destChannel] + destStartSample;
716  auto* s = source.channels[sourceChannel] + sourceStartSample;
717 
718  if (isClear)
719  {
720  isClear = false;
721 
722  if (gainToApplyToSource != Type (1))
723  FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
724  else
725  FloatVectorOperations::copy (d, s, numSamples);
726  }
727  else
728  {
729  if (gainToApplyToSource != Type (1))
730  FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples);
731  else
732  FloatVectorOperations::add (d, s, numSamples);
733  }
734  }
735  }
736 
748  void addFrom (int destChannel,
749  int destStartSample,
750  const Type* source,
751  int numSamples,
752  Type gainToApplyToSource = Type (1)) noexcept
753  {
754  jassert (isPositiveAndBelow (destChannel, numChannels));
755  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
756  jassert (source != nullptr);
757 
758  if (gainToApplyToSource != 0 && numSamples > 0)
759  {
760  auto* d = channels[destChannel] + destStartSample;
761 
762  if (isClear)
763  {
764  isClear = false;
765 
766  if (gainToApplyToSource != Type (1))
767  FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples);
768  else
769  FloatVectorOperations::copy (d, source, numSamples);
770  }
771  else
772  {
773  if (gainToApplyToSource != Type (1))
774  FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples);
775  else
776  FloatVectorOperations::add (d, source, numSamples);
777  }
778  }
779  }
780 
781 
793  void addFromWithRamp (int destChannel,
794  int destStartSample,
795  const Type* source,
796  int numSamples,
797  Type startGain,
798  Type endGain) noexcept
799  {
800  if (startGain == endGain)
801  {
802  addFrom (destChannel, destStartSample, source, numSamples, startGain);
803  }
804  else
805  {
806  jassert (isPositiveAndBelow (destChannel, numChannels));
807  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
808  jassert (source != nullptr);
809 
810  if (numSamples > 0)
811  {
812  isClear = false;
813  const auto increment = (endGain - startGain) / numSamples;
814  auto* d = channels[destChannel] + destStartSample;
815 
816  while (--numSamples >= 0)
817  {
818  *d++ += startGain * *source++;
819  startGain += increment;
820  }
821  }
822  }
823  }
824 
836  void copyFrom (int destChannel,
837  int destStartSample,
838  const AudioBuffer& source,
839  int sourceChannel,
840  int sourceStartSample,
841  int numSamples) noexcept
842  {
843  jassert (&source != this || sourceChannel != destChannel);
844  jassert (isPositiveAndBelow (destChannel, numChannels));
845  jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
846  jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
847  jassert (sourceStartSample >= 0 && numSamples >= 0 && sourceStartSample + numSamples <= source.size);
848 
849  if (numSamples > 0)
850  {
851  if (source.isClear)
852  {
853  if (! isClear)
854  FloatVectorOperations::clear (channels[destChannel] + destStartSample, numSamples);
855  }
856  else
857  {
858  isClear = false;
859  FloatVectorOperations::copy (channels[destChannel] + destStartSample,
860  source.channels[sourceChannel] + sourceStartSample,
861  numSamples);
862  }
863  }
864  }
865 
875  void copyFrom (int destChannel,
876  int destStartSample,
877  const Type* source,
878  int numSamples) noexcept
879  {
880  jassert (isPositiveAndBelow (destChannel, numChannels));
881  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
882  jassert (source != nullptr);
883 
884  if (numSamples > 0)
885  {
886  isClear = false;
887  FloatVectorOperations::copy (channels[destChannel] + destStartSample, source, numSamples);
888  }
889  }
890 
901  void copyFrom (int destChannel,
902  int destStartSample,
903  const Type* source,
904  int numSamples,
905  Type gain) noexcept
906  {
907  jassert (isPositiveAndBelow (destChannel, numChannels));
908  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
909  jassert (source != nullptr);
910 
911  if (numSamples > 0)
912  {
913  auto* d = channels[destChannel] + destStartSample;
914 
915  if (gain != Type (1))
916  {
917  if (gain == Type())
918  {
919  if (! isClear)
920  FloatVectorOperations::clear (d, numSamples);
921  }
922  else
923  {
924  isClear = false;
925  FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
926  }
927  }
928  else
929  {
930  isClear = false;
931  FloatVectorOperations::copy (d, source, numSamples);
932  }
933  }
934  }
935 
949  void copyFromWithRamp (int destChannel,
950  int destStartSample,
951  const Type* source,
952  int numSamples,
953  Type startGain,
954  Type endGain) noexcept
955  {
956  if (startGain == endGain)
957  {
958  copyFrom (destChannel, destStartSample, source, numSamples, startGain);
959  }
960  else
961  {
962  jassert (isPositiveAndBelow (destChannel, numChannels));
963  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
964  jassert (source != nullptr);
965 
966  if (numSamples > 0)
967  {
968  isClear = false;
969  const auto increment = (endGain - startGain) / numSamples;
970  auto* d = channels[destChannel] + destStartSample;
971 
972  while (--numSamples >= 0)
973  {
974  *d++ = startGain * *source++;
975  startGain += increment;
976  }
977  }
978  }
979  }
980 
987  Range<Type> findMinMax (int channel, int startSample, int numSamples) const noexcept
988  {
989  jassert (isPositiveAndBelow (channel, numChannels));
990  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
991 
992  if (isClear)
993  return { Type (0), Type (0) };
994 
995  return FloatVectorOperations::findMinAndMax (channels[channel] + startSample, numSamples);
996  }
997 
999  Type getMagnitude (int channel, int startSample, int numSamples) const noexcept
1000  {
1001  jassert (isPositiveAndBelow (channel, numChannels));
1002  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1003 
1004  if (isClear)
1005  return Type (0);
1006 
1007  auto r = findMinMax (channel, startSample, numSamples);
1008 
1009  return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1010  }
1011 
1013  Type getMagnitude (int startSample, int numSamples) const noexcept
1014  {
1015  Type mag (0);
1016 
1017  if (! isClear)
1018  for (int i = 0; i < numChannels; ++i)
1019  mag = jmax (mag, getMagnitude (i, startSample, numSamples));
1020 
1021  return mag;
1022  }
1023 
1025  Type getRMSLevel (int channel, int startSample, int numSamples) const noexcept
1026  {
1027  jassert (isPositiveAndBelow (channel, numChannels));
1028  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1029 
1030  if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1031  return Type (0);
1032 
1033  auto* data = channels[channel] + startSample;
1034  double sum = 0.0;
1035 
1036  for (int i = 0; i < numSamples; ++i)
1037  {
1038  auto sample = data[i];
1039  sum += sample * sample;
1040  }
1041 
1042  return static_cast<Type> (std::sqrt (sum / numSamples));
1043  }
1044 
1046  void reverse (int channel, int startSample, int numSamples) const noexcept
1047  {
1048  jassert (isPositiveAndBelow (channel, numChannels));
1049  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1050 
1051  if (! isClear)
1052  std::reverse (channels[channel] + startSample,
1053  channels[channel] + startSample + numSamples);
1054  }
1055 
1057  void reverse (int startSample, int numSamples) const noexcept
1058  {
1059  for (int i = 0; i < numChannels; ++i)
1060  reverse (i, startSample, numSamples);
1061  }
1062 
1063  //==============================================================================
1065  using SampleType = Type;
1066 
1067 private:
1068  //==============================================================================
1069  int numChannels = 0, size = 0;
1070  size_t allocatedBytes = 0;
1071  Type** channels;
1072  HeapBlock<char, true> allocatedData;
1073  Type* preallocatedChannelSpace[32];
1074  std::atomic<bool> isClear { false };
1075 
1076  void allocateData()
1077  {
1078  static_assert (std::alignment_of<Type>::value <= std::alignment_of<std::max_align_t>::value,
1079  "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");
1080  jassert (size >= 0);
1081 
1082  auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
1083  auto requiredSampleAlignment = std::alignment_of<Type>::value;
1084  size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1085 
1086  if (alignmentOverflow != 0)
1087  channelListSize += requiredSampleAlignment - alignmentOverflow;
1088 
1089  allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (Type) + channelListSize + 32;
1090  allocatedData.malloc (allocatedBytes);
1091  channels = reinterpret_cast<Type**> (allocatedData.get());
1092  auto chan = reinterpret_cast<Type*> (allocatedData + channelListSize);
1093 
1094  for (int i = 0; i < numChannels; ++i)
1095  {
1096  channels[i] = chan;
1097  chan += size;
1098  }
1099 
1100  channels[numChannels] = nullptr;
1101  isClear = false;
1102  }
1103 
1104  void allocateChannels (Type* const* dataToReferTo, int offset)
1105  {
1106  jassert (offset >= 0);
1107 
1108  // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
1109  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
1110  {
1111  channels = static_cast<Type**> (preallocatedChannelSpace);
1112  }
1113  else
1114  {
1115  allocatedData.malloc (numChannels + 1, sizeof (Type*));
1116  channels = reinterpret_cast<Type**> (allocatedData.get());
1117  }
1118 
1119  for (int i = 0; i < numChannels; ++i)
1120  {
1121  // you have to pass in the same number of valid pointers as numChannels
1122  jassert (dataToReferTo[i] != nullptr);
1123  channels[i] = dataToReferTo[i] + offset;
1124  }
1125 
1126  channels[numChannels] = nullptr;
1127  isClear = false;
1128  }
1129 
1130  JUCE_LEAK_DETECTOR (AudioBuffer)
1131 };
1132 
1133 //==============================================================================
1143 using AudioSampleBuffer = AudioBuffer<float>;
1144 
1145 } // 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)
Type ** getArrayOfWritePointers() noexcept
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
void applyGain(int startSample, int numSamples, Type gain) noexcept
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newNumSamples)
void copyFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
void addSample(int destChannel, int destSample, Type valueToAdd) noexcept
Type * 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
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
void reverse(int startSample, int numSamples) const noexcept
void addFromWithRamp(int destChannel, int destStartSample, const Type *source, int numSamples, Type startGain, Type endGain) noexcept
Type getMagnitude(int startSample, int numSamples) const noexcept
void reverse(int channel, int startSample, int numSamples) const noexcept
void setSample(int destChannel, int destSample, Type newValue) noexcept
void addFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples, Type gainToApplyToSource=Type(1)) noexcept
bool hasBeenCleared() const noexcept
AudioBuffer(AudioBuffer &&other) noexcept
AudioBuffer & operator=(const AudioBuffer &other)
const Type ** getArrayOfReadPointers() const 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
const Type * getReadPointer(int channelNumber) const noexcept
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
static void JUCE_CALLTYPE copyWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
static void JUCE_CALLTYPE addWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
static void JUCE_CALLTYPE add(float *dest, float amountToAdd, int numValues) noexcept
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