OpenShot Library | OpenShotAudio  0.2.2
juce_AudioSampleBuffer.h
1 
2 /** @weakgroup juce_audio_basics-buffers
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  A multi-channel buffer containing floating point audio samples.
33 
34  @tags{Audio}
35 */
36 template <typename Type>
38 {
39 public:
40  //==============================================================================
41  /** Creates an empty buffer with 0 channels and 0 length. */
42  AudioBuffer() noexcept
43  : channels (static_cast<Type**> (preallocatedChannelSpace))
44  {
45  }
46 
47  //==============================================================================
48  /** Creates a buffer with a specified number of channels and samples.
49 
50  The contents of the buffer will initially be undefined, so use clear() to
51  set all the samples to zero.
52 
53  The buffer will allocate its memory internally, and this will be released
54  when the buffer is deleted. If the memory can't be allocated, this will
55  throw a std::bad_alloc exception.
56  */
57  AudioBuffer (int numChannelsToAllocate,
58  int numSamplesToAllocate)
59  : numChannels (numChannelsToAllocate),
60  size (numSamplesToAllocate)
61  {
62  jassert (size >= 0 && numChannels >= 0);
63  allocateData();
64  }
65 
66  /** Creates a buffer using a pre-allocated block of memory.
67 
68  Note that if the buffer is resized or its number of channels is changed, it
69  will re-allocate memory internally and copy the existing data to this new area,
70  so it will then stop directly addressing this memory.
71 
72  @param dataToReferTo a pre-allocated array containing pointers to the data
73  for each channel that should be used by this buffer. The
74  buffer will only refer to this memory, it won't try to delete
75  it when the buffer is deleted or resized.
76  @param numChannelsToUse the number of channels to use - this must correspond to the
77  number of elements in the array passed in
78  @param numSamples the number of samples to use - this must correspond to the
79  size of the arrays passed in
80  */
81  AudioBuffer (Type* const* dataToReferTo,
82  int numChannelsToUse,
83  int numSamples)
84  : numChannels (numChannelsToUse),
85  size (numSamples)
86  {
87  jassert (dataToReferTo != nullptr);
88  jassert (numChannelsToUse >= 0 && numSamples >= 0);
89  allocateChannels (dataToReferTo, 0);
90  }
91 
92  /** Creates a buffer using a pre-allocated block of memory.
93 
94  Note that if the buffer is resized or its number of channels is changed, it
95  will re-allocate memory internally and copy the existing data to this new area,
96  so it will then stop directly addressing this memory.
97 
98  @param dataToReferTo a pre-allocated array containing pointers to the data
99  for each channel that should be used by this buffer. The
100  buffer will only refer to this memory, it won't try to delete
101  it when the buffer is deleted or resized.
102  @param numChannelsToUse the number of channels to use - this must correspond to the
103  number of elements in the array passed in
104  @param startSample the offset within the arrays at which the data begins
105  @param numSamples the number of samples to use - this must correspond to the
106  size of the arrays passed in
107  */
108  AudioBuffer (Type* const* dataToReferTo,
109  int numChannelsToUse,
110  int startSample,
111  int numSamples)
112  : numChannels (numChannelsToUse),
113  size (numSamples)
114  {
115  jassert (dataToReferTo != nullptr);
116  jassert (numChannelsToUse >= 0 && startSample >= 0 && numSamples >= 0);
117  allocateChannels (dataToReferTo, startSample);
118  }
119 
120  /** Copies another buffer.
121 
122  This buffer will make its own copy of the other's data, unless the buffer was created
123  using an external data buffer, in which case both buffers will just point to the same
124  shared block of data.
125  */
126  AudioBuffer (const AudioBuffer& other)
127  : numChannels (other.numChannels),
128  size (other.size),
129  allocatedBytes (other.allocatedBytes)
130  {
131  if (allocatedBytes == 0)
132  {
133  allocateChannels (other.channels, 0);
134  }
135  else
136  {
137  allocateData();
138 
139  if (other.isClear)
140  {
141  clear();
142  }
143  else
144  {
145  for (int i = 0; i < numChannels; ++i)
146  FloatVectorOperations::copy (channels[i], other.channels[i], size);
147  }
148  }
149  }
150 
151  /** Copies another buffer onto this one.
152  This buffer's size will be changed to that of the other buffer.
153  */
155  {
156  if (this != &other)
157  {
158  setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
159 
160  if (other.isClear)
161  {
162  clear();
163  }
164  else
165  {
166  isClear = false;
167 
168  for (int i = 0; i < numChannels; ++i)
169  FloatVectorOperations::copy (channels[i], other.channels[i], size);
170  }
171  }
172 
173  return *this;
174  }
175 
176  /** Destructor.
177  This will free any memory allocated by the buffer.
178  */
179  ~AudioBuffer() = default;
180 
181  /** Move constructor */
182  AudioBuffer (AudioBuffer&& other) noexcept
183  : numChannels (other.numChannels),
184  size (other.size),
185  allocatedBytes (other.allocatedBytes),
186  allocatedData (std::move (other.allocatedData)),
187  isClear (other.isClear.load())
188  {
189  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
190  {
191  channels = preallocatedChannelSpace;
192 
193  for (int i = 0; i < numChannels; ++i)
194  preallocatedChannelSpace[i] = other.channels[i];
195  }
196  else
197  {
198  channels = other.channels;
199  }
200 
201  other.numChannels = 0;
202  other.size = 0;
203  other.allocatedBytes = 0;
204  }
205 
206  /** Move assignment */
207  AudioBuffer& operator= (AudioBuffer&& other) noexcept
208  {
209  numChannels = other.numChannels;
210  size = other.size;
211  allocatedBytes = other.allocatedBytes;
212  allocatedData = std::move (other.allocatedData);
213  isClear = other.isClear.load();
214 
215  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
216  {
217  channels = preallocatedChannelSpace;
218 
219  for (int i = 0; i < numChannels; ++i)
220  preallocatedChannelSpace[i] = other.channels[i];
221  }
222  else
223  {
224  channels = other.channels;
225  }
226 
227  other.numChannels = 0;
228  other.size = 0;
229  other.allocatedBytes = 0;
230  return *this;
231  }
232 
233  //==============================================================================
234  /** Returns the number of channels of audio data that this buffer contains.
235  @see getNumSamples, getReadPointer, getWritePointer
236  */
237  int getNumChannels() const noexcept { return numChannels; }
238 
239  /** Returns the number of samples allocated in each of the buffer's channels.
240  @see getNumChannels, getReadPointer, getWritePointer
241  */
242  int getNumSamples() const noexcept { return size; }
243 
244  /** Returns a pointer to an array of read-only samples in one of the buffer's channels.
245  For speed, this doesn't check whether the channel number is out of range,
246  so be careful when using it!
247  If you need to write to the data, do NOT call this method and const_cast the
248  result! Instead, you must call getWritePointer so that the buffer knows you're
249  planning on modifying the data.
250  */
251  const Type* getReadPointer (int channelNumber) const noexcept
252  {
253  jassert (isPositiveAndBelow (channelNumber, numChannels));
254  return channels[channelNumber];
255  }
256 
257  /** Returns a pointer to an array of read-only samples in one of the buffer's channels.
258  For speed, this doesn't check whether the channel number or index are out of range,
259  so be careful when using it!
260  If you need to write to the data, do NOT call this method and const_cast the
261  result! Instead, you must call getWritePointer so that the buffer knows you're
262  planning on modifying the data.
263  */
264  const Type* getReadPointer (int channelNumber, int sampleIndex) const noexcept
265  {
266  jassert (isPositiveAndBelow (channelNumber, numChannels));
267  jassert (isPositiveAndBelow (sampleIndex, size));
268  return channels[channelNumber] + sampleIndex;
269  }
270 
271  /** Returns a writeable pointer to one of the buffer's channels.
272  For speed, this doesn't check whether the channel number is out of range,
273  so be careful when using it!
274  Note that if you're not planning on writing to the data, you should always
275  use getReadPointer instead.
276  */
277  Type* getWritePointer (int channelNumber) noexcept
278  {
279  jassert (isPositiveAndBelow (channelNumber, numChannels));
280  isClear = false;
281  return channels[channelNumber];
282  }
283 
284  /** Returns a writeable pointer to one of the buffer's channels.
285  For speed, this doesn't check whether the channel number or index are out of range,
286  so be careful when using it!
287  Note that if you're not planning on writing to the data, you should
288  use getReadPointer instead.
289  */
290  Type* getWritePointer (int channelNumber, int sampleIndex) noexcept
291  {
292  jassert (isPositiveAndBelow (channelNumber, numChannels));
293  jassert (isPositiveAndBelow (sampleIndex, size));
294  isClear = false;
295  return channels[channelNumber] + sampleIndex;
296  }
297 
298  /** Returns an array of pointers to the channels in the buffer.
299 
300  Don't modify any of the pointers that are returned, and bear in mind that
301  these will become invalid if the buffer is resized.
302  */
303  const Type** getArrayOfReadPointers() const noexcept { return const_cast<const Type**> (channels); }
304 
305  /** Returns an array of pointers to the channels in the buffer.
306 
307  Don't modify any of the pointers that are returned, and bear in mind that
308  these will become invalid if the buffer is resized.
309  */
310  Type** getArrayOfWritePointers() noexcept { isClear = false; return channels; }
311 
312  //==============================================================================
313  /** Changes the buffer's size or number of channels.
314 
315  This can expand or contract the buffer's length, and add or remove channels.
316 
317  If keepExistingContent is true, it will try to preserve as much of the
318  old data as it can in the new buffer.
319 
320  If clearExtraSpace is true, then any extra channels or space that is
321  allocated will be also be cleared. If false, then this space is left
322  uninitialised.
323 
324  If avoidReallocating is true, then changing the buffer's size won't reduce the
325  amount of memory that is currently allocated (but it will still increase it if
326  the new size is bigger than the amount it currently has). If this is false, then
327  a new allocation will be done so that the buffer uses takes up the minimum amount
328  of memory that it needs.
329 
330  Note that if keepExistingContent and avoidReallocating are both true, then it will
331  only avoid reallocating if neither the channel count or length in samples increase.
332 
333  If the required memory can't be allocated, this will throw a std::bad_alloc exception.
334  */
335  void setSize (int newNumChannels,
336  int newNumSamples,
337  bool keepExistingContent = false,
338  bool clearExtraSpace = false,
339  bool avoidReallocating = false)
340  {
341  jassert (newNumChannels >= 0);
342  jassert (newNumSamples >= 0);
343 
344  if (newNumSamples != size || newNumChannels != numChannels)
345  {
346  auto allocatedSamplesPerChannel = ((size_t) newNumSamples + 3) & ~3u;
347  auto channelListSize = ((static_cast<size_t> (1 + newNumChannels) * sizeof (Type*)) + 15) & ~15u;
348  auto newTotalBytes = ((size_t) newNumChannels * (size_t) allocatedSamplesPerChannel * sizeof (Type))
349  + channelListSize + 32;
350 
351  if (keepExistingContent)
352  {
353  if (avoidReallocating && newNumChannels <= numChannels && newNumSamples <= size)
354  {
355  // no need to do any remapping in this case, as the channel pointers will remain correct!
356  }
357  else
358  {
359  HeapBlock<char, true> newData;
360  newData.allocate (newTotalBytes, clearExtraSpace || isClear);
361 
362  auto numSamplesToCopy = (size_t) jmin (newNumSamples, size);
363 
364  auto newChannels = reinterpret_cast<Type**> (newData.get());
365  auto newChan = reinterpret_cast<Type*> (newData + channelListSize);
366 
367  for (int j = 0; j < newNumChannels; ++j)
368  {
369  newChannels[j] = newChan;
370  newChan += allocatedSamplesPerChannel;
371  }
372 
373  if (! isClear)
374  {
375  auto numChansToCopy = jmin (numChannels, newNumChannels);
376 
377  for (int i = 0; i < numChansToCopy; ++i)
378  FloatVectorOperations::copy (newChannels[i], channels[i], (int) numSamplesToCopy);
379  }
380 
381  allocatedData.swapWith (newData);
382  allocatedBytes = newTotalBytes;
383  channels = newChannels;
384  }
385  }
386  else
387  {
388  if (avoidReallocating && allocatedBytes >= newTotalBytes)
389  {
390  if (clearExtraSpace || isClear)
391  allocatedData.clear (newTotalBytes);
392  }
393  else
394  {
395  allocatedBytes = newTotalBytes;
396  allocatedData.allocate (newTotalBytes, clearExtraSpace || isClear);
397  channels = reinterpret_cast<Type**> (allocatedData.get());
398  }
399 
400  auto* chan = reinterpret_cast<Type*> (allocatedData + channelListSize);
401 
402  for (int i = 0; i < newNumChannels; ++i)
403  {
404  channels[i] = chan;
405  chan += allocatedSamplesPerChannel;
406  }
407  }
408 
409  channels[newNumChannels] = nullptr;
410  size = newNumSamples;
411  numChannels = newNumChannels;
412  }
413  }
414 
415  /** Makes this buffer point to a pre-allocated set of channel data arrays.
416 
417  There's also a constructor that lets you specify arrays like this, but this
418  lets you change the channels dynamically.
419 
420  Note that if the buffer is resized or its number of channels is changed, it
421  will re-allocate memory internally and copy the existing data to this new area,
422  so it will then stop directly addressing this memory.
423 
424  @param dataToReferTo a pre-allocated array containing pointers to the data
425  for each channel that should be used by this buffer. The
426  buffer will only refer to this memory, it won't try to delete
427  it when the buffer is deleted or resized.
428  @param newNumChannels the number of channels to use - this must correspond to the
429  number of elements in the array passed in
430  @param newStartSample the offset within the arrays at which the data begins
431  @param newNumSamples the number of samples to use - this must correspond to the
432  size of the arrays passed in
433  */
434  void setDataToReferTo (Type** dataToReferTo,
435  int newNumChannels,
436  int newStartSample,
437  int newNumSamples)
438  {
439  jassert (dataToReferTo != nullptr);
440  jassert (newNumChannels >= 0 && newNumSamples >= 0);
441 
442  if (allocatedBytes != 0)
443  {
444  allocatedBytes = 0;
445  allocatedData.free();
446  }
447 
448  numChannels = newNumChannels;
449  size = newNumSamples;
450 
451  allocateChannels (dataToReferTo, newStartSample);
452  jassert (! isClear);
453  }
454 
455  /** Makes this buffer point to a pre-allocated set of channel data arrays.
456 
457  There's also a constructor that lets you specify arrays like this, but this
458  lets you change the channels dynamically.
459 
460  Note that if the buffer is resized or its number of channels is changed, it
461  will re-allocate memory internally and copy the existing data to this new area,
462  so it will then stop directly addressing this memory.
463 
464  @param dataToReferTo a pre-allocated array containing pointers to the data
465  for each channel that should be used by this buffer. The
466  buffer will only refer to this memory, it won't try to delete
467  it when the buffer is deleted or resized.
468  @param newNumChannels the number of channels to use - this must correspond to the
469  number of elements in the array passed in
470  @param newNumSamples the number of samples to use - this must correspond to the
471  size of the arrays passed in
472  */
473  void setDataToReferTo (Type** dataToReferTo,
474  int newNumChannels,
475  int newNumSamples)
476  {
477  setDataToReferTo (dataToReferTo, newNumChannels, 0, newNumSamples);
478  }
479 
480  /** Resizes this buffer to match the given one, and copies all of its content across.
481  The source buffer can contain a different floating point type, so this can be used to
482  convert between 32 and 64 bit float buffer types.
483  */
484  template <typename OtherType>
485  void makeCopyOf (const AudioBuffer<OtherType>& other, bool avoidReallocating = false)
486  {
487  setSize (other.getNumChannels(), other.getNumSamples(), false, false, avoidReallocating);
488 
489  if (other.hasBeenCleared())
490  {
491  clear();
492  }
493  else
494  {
495  isClear = false;
496 
497  for (int chan = 0; chan < numChannels; ++chan)
498  {
499  auto* dest = channels[chan];
500  auto* src = other.getReadPointer (chan);
501 
502  for (int i = 0; i < size; ++i)
503  dest[i] = static_cast<Type> (src[i]);
504  }
505  }
506  }
507 
508  //==============================================================================
509  /** Clears all the samples in all channels. */
510  void clear() noexcept
511  {
512  if (! isClear)
513  {
514  for (int i = 0; i < numChannels; ++i)
515  FloatVectorOperations::clear (channels[i], size);
516 
517  isClear = true;
518  }
519  }
520 
521  /** Clears a specified region of all the channels.
522 
523  For speed, this doesn't check whether the channel and sample number
524  are in-range, so be careful!
525  */
526  void clear (int startSample, int numSamples) noexcept
527  {
528  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
529 
530  if (! isClear)
531  {
532  if (startSample == 0 && numSamples == size)
533  isClear = true;
534 
535  for (int i = 0; i < numChannels; ++i)
536  FloatVectorOperations::clear (channels[i] + startSample, numSamples);
537  }
538  }
539 
540  /** Clears a specified region of just one channel.
541 
542  For speed, this doesn't check whether the channel and sample number
543  are in-range, so be careful!
544  */
545  void clear (int channel, int startSample, int numSamples) noexcept
546  {
547  jassert (isPositiveAndBelow (channel, numChannels));
548  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
549 
550  if (! isClear)
551  FloatVectorOperations::clear (channels[channel] + startSample, numSamples);
552  }
553 
554  /** Returns true if the buffer has been entirely cleared.
555  Note that this does not actually measure the contents of the buffer - it simply
556  returns a flag that is set when the buffer is cleared, and which is reset whenever
557  functions like getWritePointer() are invoked. That means the method does not take
558  any time, but it may return false negatives when in fact the buffer is still empty.
559  */
560  bool hasBeenCleared() const noexcept { return isClear; }
561 
562  //==============================================================================
563  /** Returns a sample from the buffer.
564  The channel and index are not checked - they are expected to be in-range. If not,
565  an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
566  territory.
567  */
568  Type getSample (int channel, int sampleIndex) const noexcept
569  {
570  jassert (isPositiveAndBelow (channel, numChannels));
571  jassert (isPositiveAndBelow (sampleIndex, size));
572  return *(channels[channel] + sampleIndex);
573  }
574 
575  /** Sets a sample in the buffer.
576  The channel and index are not checked - they are expected to be in-range. If not,
577  an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
578  territory.
579  */
580  void setSample (int destChannel, int destSample, Type newValue) noexcept
581  {
582  jassert (isPositiveAndBelow (destChannel, numChannels));
583  jassert (isPositiveAndBelow (destSample, size));
584  *(channels[destChannel] + destSample) = newValue;
585  isClear = false;
586  }
587 
588  /** Adds a value to a sample in the buffer.
589  The channel and index are not checked - they are expected to be in-range. If not,
590  an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
591  territory.
592  */
593  void addSample (int destChannel, int destSample, Type valueToAdd) noexcept
594  {
595  jassert (isPositiveAndBelow (destChannel, numChannels));
596  jassert (isPositiveAndBelow (destSample, size));
597  *(channels[destChannel] + destSample) += valueToAdd;
598  isClear = false;
599  }
600 
601  /** Applies a gain multiple to a region of one channel.
602 
603  For speed, this doesn't check whether the channel and sample number
604  are in-range, so be careful!
605  */
606  void applyGain (int channel, int startSample, int numSamples, Type gain) noexcept
607  {
608  jassert (isPositiveAndBelow (channel, numChannels));
609  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
610 
611  if (gain != Type (1) && ! isClear)
612  {
613  auto* d = channels[channel] + startSample;
614 
615  if (gain == Type())
616  FloatVectorOperations::clear (d, numSamples);
617  else
618  FloatVectorOperations::multiply (d, gain, numSamples);
619  }
620  }
621 
622  /** Applies a gain multiple to a region of all the channels.
623 
624  For speed, this doesn't check whether the sample numbers
625  are in-range, so be careful!
626  */
627  void applyGain (int startSample, int numSamples, Type gain) noexcept
628  {
629  for (int i = 0; i < numChannels; ++i)
630  applyGain (i, startSample, numSamples, gain);
631  }
632 
633  /** Applies a gain multiple to all the audio data. */
634  void applyGain (Type gain) noexcept
635  {
636  applyGain (0, size, gain);
637  }
638 
639  /** Applies a range of gains to a region of a channel.
640 
641  The gain that is applied to each sample will vary from
642  startGain on the first sample to endGain on the last Sample,
643  so it can be used to do basic fades.
644 
645  For speed, this doesn't check whether the sample numbers
646  are in-range, so be careful!
647  */
648  void applyGainRamp (int channel, int startSample, int numSamples,
649  Type startGain, Type endGain) noexcept
650  {
651  if (! isClear)
652  {
653  if (startGain == endGain)
654  {
655  applyGain (channel, startSample, numSamples, startGain);
656  }
657  else
658  {
659  jassert (isPositiveAndBelow (channel, numChannels));
660  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
661 
662  const auto increment = (endGain - startGain) / (float) numSamples;
663  auto* d = channels[channel] + startSample;
664 
665  while (--numSamples >= 0)
666  {
667  *d++ *= startGain;
668  startGain += increment;
669  }
670  }
671  }
672  }
673 
674  /** Applies a range of gains to a region of all channels.
675 
676  The gain that is applied to each sample will vary from
677  startGain on the first sample to endGain on the last Sample,
678  so it can be used to do basic fades.
679 
680  For speed, this doesn't check whether the sample numbers
681  are in-range, so be careful!
682  */
683  void applyGainRamp (int startSample, int numSamples,
684  Type startGain, Type endGain) noexcept
685  {
686  for (int i = 0; i < numChannels; ++i)
687  applyGainRamp (i, startSample, numSamples, startGain, endGain);
688  }
689 
690  /** Adds samples from another buffer to this one.
691 
692  @param destChannel the channel within this buffer to add the samples to
693  @param destStartSample the start sample within this buffer's channel
694  @param source the source buffer to add from
695  @param sourceChannel the channel within the source buffer to read from
696  @param sourceStartSample the offset within the source buffer's channel to start reading samples from
697  @param numSamples the number of samples to process
698  @param gainToApplyToSource an optional gain to apply to the source samples before they are
699  added to this buffer's samples
700 
701  @see copyFrom
702  */
703  void addFrom (int destChannel,
704  int destStartSample,
705  const AudioBuffer& source,
706  int sourceChannel,
707  int sourceStartSample,
708  int numSamples,
709  Type gainToApplyToSource = Type (1)) noexcept
710  {
711  jassert (&source != this || sourceChannel != destChannel);
712  jassert (isPositiveAndBelow (destChannel, numChannels));
713  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
714  jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
715  jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
716 
717  if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear)
718  {
719  auto* d = channels[destChannel] + destStartSample;
720  auto* s = source.channels[sourceChannel] + sourceStartSample;
721 
722  if (isClear)
723  {
724  isClear = false;
725 
726  if (gainToApplyToSource != Type (1))
727  FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
728  else
729  FloatVectorOperations::copy (d, s, numSamples);
730  }
731  else
732  {
733  if (gainToApplyToSource != Type (1))
734  FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples);
735  else
736  FloatVectorOperations::add (d, s, numSamples);
737  }
738  }
739  }
740 
741  /** Adds samples from an array of floats to one of the channels.
742 
743  @param destChannel the channel within this buffer to add the samples to
744  @param destStartSample the start sample within this buffer's channel
745  @param source the source data to use
746  @param numSamples the number of samples to process
747  @param gainToApplyToSource an optional gain to apply to the source samples before they are
748  added to this buffer's samples
749 
750  @see copyFrom
751  */
752  void addFrom (int destChannel,
753  int destStartSample,
754  const Type* source,
755  int numSamples,
756  Type gainToApplyToSource = Type (1)) noexcept
757  {
758  jassert (isPositiveAndBelow (destChannel, numChannels));
759  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
760  jassert (source != nullptr);
761 
762  if (gainToApplyToSource != 0 && numSamples > 0)
763  {
764  auto* d = channels[destChannel] + destStartSample;
765 
766  if (isClear)
767  {
768  isClear = false;
769 
770  if (gainToApplyToSource != Type (1))
771  FloatVectorOperations::copyWithMultiply (d, source, gainToApplyToSource, numSamples);
772  else
773  FloatVectorOperations::copy (d, source, numSamples);
774  }
775  else
776  {
777  if (gainToApplyToSource != Type (1))
778  FloatVectorOperations::addWithMultiply (d, source, gainToApplyToSource, numSamples);
779  else
780  FloatVectorOperations::add (d, source, numSamples);
781  }
782  }
783  }
784 
785 
786  /** Adds samples from an array of floats, applying a gain ramp to them.
787 
788  @param destChannel the channel within this buffer to add the samples to
789  @param destStartSample the start sample within this buffer's channel
790  @param source the source data to use
791  @param numSamples the number of samples to process
792  @param startGain the gain to apply to the first sample (this is multiplied with
793  the source samples before they are added to this buffer)
794  @param endGain the gain to apply to the final sample. The gain is linearly
795  interpolated between the first and last samples.
796  */
797  void addFromWithRamp (int destChannel,
798  int destStartSample,
799  const Type* source,
800  int numSamples,
801  Type startGain,
802  Type endGain) noexcept
803  {
804  if (startGain == endGain)
805  {
806  addFrom (destChannel, destStartSample, source, numSamples, startGain);
807  }
808  else
809  {
810  jassert (isPositiveAndBelow (destChannel, numChannels));
811  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
812  jassert (source != nullptr);
813 
814  if (numSamples > 0)
815  {
816  isClear = false;
817  const auto increment = (endGain - startGain) / numSamples;
818  auto* d = channels[destChannel] + destStartSample;
819 
820  while (--numSamples >= 0)
821  {
822  *d++ += startGain * *source++;
823  startGain += increment;
824  }
825  }
826  }
827  }
828 
829  /** Copies samples from another buffer to this one.
830 
831  @param destChannel the channel within this buffer to copy the samples to
832  @param destStartSample the start sample within this buffer's channel
833  @param source the source buffer to read from
834  @param sourceChannel the channel within the source buffer to read from
835  @param sourceStartSample the offset within the source buffer's channel to start reading samples from
836  @param numSamples the number of samples to process
837 
838  @see addFrom
839  */
840  void copyFrom (int destChannel,
841  int destStartSample,
842  const AudioBuffer& source,
843  int sourceChannel,
844  int sourceStartSample,
845  int numSamples) noexcept
846  {
847  jassert (&source != this || sourceChannel != destChannel);
848  jassert (isPositiveAndBelow (destChannel, numChannels));
849  jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
850  jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
851  jassert (sourceStartSample >= 0 && numSamples >= 0 && sourceStartSample + numSamples <= source.size);
852 
853  if (numSamples > 0)
854  {
855  if (source.isClear)
856  {
857  if (! isClear)
858  FloatVectorOperations::clear (channels[destChannel] + destStartSample, numSamples);
859  }
860  else
861  {
862  isClear = false;
863  FloatVectorOperations::copy (channels[destChannel] + destStartSample,
864  source.channels[sourceChannel] + sourceStartSample,
865  numSamples);
866  }
867  }
868  }
869 
870  /** Copies samples from an array of floats into one of the channels.
871 
872  @param destChannel the channel within this buffer to copy the samples to
873  @param destStartSample the start sample within this buffer's channel
874  @param source the source buffer to read from
875  @param numSamples the number of samples to process
876 
877  @see addFrom
878  */
879  void copyFrom (int destChannel,
880  int destStartSample,
881  const Type* source,
882  int numSamples) noexcept
883  {
884  jassert (isPositiveAndBelow (destChannel, numChannels));
885  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
886  jassert (source != nullptr);
887 
888  if (numSamples > 0)
889  {
890  isClear = false;
891  FloatVectorOperations::copy (channels[destChannel] + destStartSample, source, numSamples);
892  }
893  }
894 
895  /** Copies samples from an array of floats into one of the channels, applying a gain to it.
896 
897  @param destChannel the channel within this buffer to copy the samples to
898  @param destStartSample the start sample within this buffer's channel
899  @param source the source buffer to read from
900  @param numSamples the number of samples to process
901  @param gain the gain to apply
902 
903  @see addFrom
904  */
905  void copyFrom (int destChannel,
906  int destStartSample,
907  const Type* source,
908  int numSamples,
909  Type gain) noexcept
910  {
911  jassert (isPositiveAndBelow (destChannel, numChannels));
912  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
913  jassert (source != nullptr);
914 
915  if (numSamples > 0)
916  {
917  auto* d = channels[destChannel] + destStartSample;
918 
919  if (gain != Type (1))
920  {
921  if (gain == Type())
922  {
923  if (! isClear)
924  FloatVectorOperations::clear (d, numSamples);
925  }
926  else
927  {
928  isClear = false;
929  FloatVectorOperations::copyWithMultiply (d, source, gain, numSamples);
930  }
931  }
932  else
933  {
934  isClear = false;
935  FloatVectorOperations::copy (d, source, numSamples);
936  }
937  }
938  }
939 
940  /** Copies samples from an array of floats into one of the channels, applying a gain ramp.
941 
942  @param destChannel the channel within this buffer to copy the samples to
943  @param destStartSample the start sample within this buffer's channel
944  @param source the source buffer to read from
945  @param numSamples the number of samples to process
946  @param startGain the gain to apply to the first sample (this is multiplied with
947  the source samples before they are copied to this buffer)
948  @param endGain the gain to apply to the final sample. The gain is linearly
949  interpolated between the first and last samples.
950 
951  @see addFrom
952  */
953  void copyFromWithRamp (int destChannel,
954  int destStartSample,
955  const Type* source,
956  int numSamples,
957  Type startGain,
958  Type endGain) noexcept
959  {
960  if (startGain == endGain)
961  {
962  copyFrom (destChannel, destStartSample, source, numSamples, startGain);
963  }
964  else
965  {
966  jassert (isPositiveAndBelow (destChannel, numChannels));
967  jassert (destStartSample >= 0 && numSamples >= 0 && destStartSample + numSamples <= size);
968  jassert (source != nullptr);
969 
970  if (numSamples > 0)
971  {
972  isClear = false;
973  const auto increment = (endGain - startGain) / numSamples;
974  auto* d = channels[destChannel] + destStartSample;
975 
976  while (--numSamples >= 0)
977  {
978  *d++ = startGain * *source++;
979  startGain += increment;
980  }
981  }
982  }
983  }
984 
985  /** Returns a Range indicating the lowest and highest sample values in a given section.
986 
987  @param channel the channel to read from
988  @param startSample the start sample within the channel
989  @param numSamples the number of samples to check
990  */
991  Range<Type> findMinMax (int channel, int startSample, int numSamples) const noexcept
992  {
993  jassert (isPositiveAndBelow (channel, numChannels));
994  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
995 
996  if (isClear)
997  return { Type (0), Type (0) };
998 
999  return FloatVectorOperations::findMinAndMax (channels[channel] + startSample, numSamples);
1000  }
1001 
1002  /** Finds the highest absolute sample value within a region of a channel. */
1003  Type getMagnitude (int channel, int startSample, int numSamples) const noexcept
1004  {
1005  jassert (isPositiveAndBelow (channel, numChannels));
1006  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1007 
1008  if (isClear)
1009  return Type (0);
1010 
1011  auto r = findMinMax (channel, startSample, numSamples);
1012 
1013  return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
1014  }
1015 
1016  /** Finds the highest absolute sample value within a region on all channels. */
1017  Type getMagnitude (int startSample, int numSamples) const noexcept
1018  {
1019  Type mag (0);
1020 
1021  if (! isClear)
1022  for (int i = 0; i < numChannels; ++i)
1023  mag = jmax (mag, getMagnitude (i, startSample, numSamples));
1024 
1025  return mag;
1026  }
1027 
1028  /** Returns the root mean squared level for a region of a channel. */
1029  Type getRMSLevel (int channel, int startSample, int numSamples) const noexcept
1030  {
1031  jassert (isPositiveAndBelow (channel, numChannels));
1032  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1033 
1034  if (numSamples <= 0 || channel < 0 || channel >= numChannels || isClear)
1035  return Type (0);
1036 
1037  auto* data = channels[channel] + startSample;
1038  double sum = 0.0;
1039 
1040  for (int i = 0; i < numSamples; ++i)
1041  {
1042  auto sample = data[i];
1043  sum += sample * sample;
1044  }
1045 
1046  return static_cast<Type> (std::sqrt (sum / numSamples));
1047  }
1048 
1049  /** Reverses a part of a channel. */
1050  void reverse (int channel, int startSample, int numSamples) const noexcept
1051  {
1052  jassert (isPositiveAndBelow (channel, numChannels));
1053  jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
1054 
1055  if (! isClear)
1056  std::reverse (channels[channel] + startSample,
1057  channels[channel] + startSample + numSamples);
1058  }
1059 
1060  /** Reverses a part of the buffer. */
1061  void reverse (int startSample, int numSamples) const noexcept
1062  {
1063  for (int i = 0; i < numChannels; ++i)
1064  reverse (i, startSample, numSamples);
1065  }
1066 
1067  //==============================================================================
1068  /** This allows templated code that takes an AudioBuffer to access its sample type. */
1069  using SampleType = Type;
1070 
1071 private:
1072  //==============================================================================
1073  int numChannels = 0, size = 0;
1074  size_t allocatedBytes = 0;
1075  Type** channels;
1076  HeapBlock<char, true> allocatedData;
1077  Type* preallocatedChannelSpace[32];
1078  std::atomic<bool> isClear { false };
1079 
1080  void allocateData()
1081  {
1082  static_assert (std::alignment_of<Type>::value <= std::alignment_of<std::max_align_t>::value,
1083  "AudioBuffer cannot hold types with alignment requirements larger than that guaranteed by malloc");
1084  jassert (size >= 0);
1085 
1086  auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
1087  auto requiredSampleAlignment = std::alignment_of<Type>::value;
1088  size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
1089 
1090  if (alignmentOverflow != 0)
1091  channelListSize += requiredSampleAlignment - alignmentOverflow;
1092 
1093  allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (Type) + channelListSize + 32;
1094  allocatedData.malloc (allocatedBytes);
1095  channels = reinterpret_cast<Type**> (allocatedData.get());
1096  auto chan = reinterpret_cast<Type*> (allocatedData + channelListSize);
1097 
1098  for (int i = 0; i < numChannels; ++i)
1099  {
1100  channels[i] = chan;
1101  chan += size;
1102  }
1103 
1104  channels[numChannels] = nullptr;
1105  isClear = false;
1106  }
1107 
1108  void allocateChannels (Type* const* dataToReferTo, int offset)
1109  {
1110  jassert (offset >= 0);
1111 
1112  // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
1113  if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
1114  {
1115  channels = static_cast<Type**> (preallocatedChannelSpace);
1116  }
1117  else
1118  {
1119  allocatedData.malloc (numChannels + 1, sizeof (Type*));
1120  channels = reinterpret_cast<Type**> (allocatedData.get());
1121  }
1122 
1123  for (int i = 0; i < numChannels; ++i)
1124  {
1125  // you have to pass in the same number of valid pointers as numChannels
1126  jassert (dataToReferTo[i] != nullptr);
1127  channels[i] = dataToReferTo[i] + offset;
1128  }
1129 
1130  channels[numChannels] = nullptr;
1131  isClear = false;
1132  }
1133 
1134  JUCE_LEAK_DETECTOR (AudioBuffer)
1135 };
1136 
1137 //==============================================================================
1138 /**
1139  A multi-channel buffer of 32-bit floating point audio samples.
1140 
1141  This type is here for backwards compatibility with the older AudioSampleBuffer
1142  class, which was fixed for 32-bit data, but is otherwise the same as the new
1143  templated AudioBuffer class.
1144 
1145  @see AudioBuffer
1146 */
1147 using AudioSampleBuffer = AudioBuffer<float>;
1148 
1149 } // namespace juce
1150 
1151 /** @}*/
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.
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 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.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
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.
void applyGain(Type gain) noexcept
Applies a gain multiple to all the audio data.
AudioBuffer(const AudioBuffer &other)
Copies another buffer.
Type ** getArrayOfWritePointers() noexcept
Returns an array of pointers to the channels in the buffer.
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 applyGain(int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of all the channels.
void setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
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 * getWritePointer(int channelNumber, int sampleIndex) noexcept
Returns a writeable pointer to one of the buffer's channels.
Type getRMSLevel(int channel, int startSample, int numSamples) const noexcept
Returns the root mean squared level for a region of a channel.
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.
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.
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 setDataToReferTo(Type **dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
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.
AudioBuffer(AudioBuffer &&other) noexcept
Move constructor.
Type SampleType
This allows templated code that takes an AudioBuffer to access its sample type.
AudioBuffer & operator=(const AudioBuffer &other)
Copies another buffer onto this one.
AudioBuffer() noexcept
Creates an empty buffer with 0 channels and 0 length.
const Type ** getArrayOfReadPointers() const noexcept
Returns an array of pointers to the channels in the buffer.
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.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
Applies a gain multiple to a region of one channel.
static void JUCE_CALLTYPE multiply(float *dest, const float *src, int numValues) noexcept
Multiplies the destination values by the source values.
static void JUCE_CALLTYPE clear(float *dest, int numValues) noexcept
Clears a vector of floats.
static void JUCE_CALLTYPE copyWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
Copies a vector of floats, multiplying each value by a given multiplier.
static void JUCE_CALLTYPE copy(float *dest, const float *src, int numValues) noexcept
Copies a vector of floats.
static void JUCE_CALLTYPE addWithMultiply(float *dest, const float *src, float multiplier, int numValues) noexcept
Multiplies each source value by the given multiplier, then adds it to the destination value.
static Range< float > JUCE_CALLTYPE findMinAndMax(const float *src, int numValues) noexcept
Finds the minimum and maximum values in the given array.
static void JUCE_CALLTYPE add(float *dest, float amountToAdd, int numValues) noexcept
Adds a fixed value to the destination values.
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
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.
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:44