2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
30 #include "juce_AudioSampleBuffer.h"
31 #include "../audio_file_formats/juce_AudioFormatReader.h"
32 #include "../audio_file_formats/juce_AudioFormatWriter.h"
35 //==============================================================================
36 AudioSampleBuffer::AudioSampleBuffer (const int numChannels_
,
37 const int numSamples
) noexcept
38 : numChannels (numChannels_
),
41 jassert (numSamples
>= 0);
42 jassert (numChannels_
> 0);
47 AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer
& other
) noexcept
48 : numChannels (other
.numChannels
),
52 const size_t numBytes
= size
* sizeof (float);
54 for (int i
= 0; i
< numChannels
; ++i
)
55 memcpy (channels
[i
], other
.channels
[i
], numBytes
);
58 void AudioSampleBuffer::allocateData()
60 const size_t channelListSize
= (numChannels
+ 1) * sizeof (float*);
61 allocatedBytes
= (int) (numChannels
* size
* sizeof (float) + channelListSize
+ 32);
62 allocatedData
.malloc (allocatedBytes
);
63 channels
= reinterpret_cast <float**> (allocatedData
.getData());
65 float* chan
= (float*) (allocatedData
+ channelListSize
);
66 for (int i
= 0; i
< numChannels
; ++i
)
72 channels
[numChannels
] = 0;
75 AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo
,
76 const int numChannels_
,
77 const int numSamples
) noexcept
78 : numChannels (numChannels_
),
82 jassert (numChannels_
> 0);
83 allocateChannels (dataToReferTo
, 0);
86 AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo
,
87 const int numChannels_
,
88 const int startSample
,
89 const int numSamples
) noexcept
90 : numChannels (numChannels_
),
94 jassert (numChannels_
> 0);
95 allocateChannels (dataToReferTo
, startSample
);
98 void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo
,
99 const int newNumChannels
,
100 const int newNumSamples
) noexcept
102 jassert (newNumChannels
> 0);
105 allocatedData
.free();
107 numChannels
= newNumChannels
;
108 size
= newNumSamples
;
110 allocateChannels (dataToReferTo
, 0);
113 void AudioSampleBuffer::allocateChannels (float** const dataToReferTo
, int offset
)
115 // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
116 if (numChannels
< numElementsInArray (preallocatedChannelSpace
))
118 channels
= static_cast <float**> (preallocatedChannelSpace
);
122 allocatedData
.malloc (numChannels
+ 1, sizeof (float*));
123 channels
= reinterpret_cast <float**> (allocatedData
.getData());
126 for (int i
= 0; i
< numChannels
; ++i
)
128 // you have to pass in the same number of valid pointers as numChannels
129 jassert (dataToReferTo
[i
] != nullptr);
131 channels
[i
] = dataToReferTo
[i
] + offset
;
134 channels
[numChannels
] = 0;
137 AudioSampleBuffer
& AudioSampleBuffer::operator= (const AudioSampleBuffer
& other
) noexcept
141 setSize (other
.getNumChannels(), other
.getNumSamples(), false, false, false);
143 const size_t numBytes
= size
* sizeof (float);
145 for (int i
= 0; i
< numChannels
; ++i
)
146 memcpy (channels
[i
], other
.channels
[i
], numBytes
);
152 AudioSampleBuffer::~AudioSampleBuffer() noexcept
156 void AudioSampleBuffer::setSize (const int newNumChannels
,
157 const int newNumSamples
,
158 const bool keepExistingContent
,
159 const bool clearExtraSpace
,
160 const bool avoidReallocating
) noexcept
162 jassert (newNumChannels
> 0);
164 if (newNumSamples
!= size
|| newNumChannels
!= numChannels
)
166 const size_t channelListSize
= (newNumChannels
+ 1) * sizeof (float*);
167 const size_t newTotalBytes
= (newNumChannels
* newNumSamples
* sizeof (float)) + channelListSize
+ 32;
169 if (keepExistingContent
)
171 HeapBlock
<char> newData
;
172 newData
.allocate (newTotalBytes
, clearExtraSpace
);
174 const int numChansToCopy
= jmin (numChannels
, newNumChannels
);
175 const size_t numBytesToCopy
= sizeof (float) * jmin (newNumSamples
, size
);
177 float** const newChannels
= reinterpret_cast <float**> (newData
.getData());
178 float* newChan
= reinterpret_cast <float*> (newData
+ channelListSize
);
179 for (int i
= 0; i
< numChansToCopy
; ++i
)
181 memcpy (newChan
, channels
[i
], numBytesToCopy
);
182 newChannels
[i
] = newChan
;
183 newChan
+= newNumSamples
;
186 allocatedData
.swapWith (newData
);
187 allocatedBytes
= (int) newTotalBytes
;
188 channels
= newChannels
;
192 if (avoidReallocating
&& allocatedBytes
>= newTotalBytes
)
195 allocatedData
.clear (newTotalBytes
);
199 allocatedBytes
= newTotalBytes
;
200 allocatedData
.allocate (newTotalBytes
, clearExtraSpace
);
201 channels
= reinterpret_cast <float**> (allocatedData
.getData());
204 float* chan
= reinterpret_cast <float*> (allocatedData
+ channelListSize
);
205 for (int i
= 0; i
< newNumChannels
; ++i
)
208 chan
+= newNumSamples
;
212 channels
[newNumChannels
] = 0;
213 size
= newNumSamples
;
214 numChannels
= newNumChannels
;
218 void AudioSampleBuffer::clear() noexcept
220 for (int i
= 0; i
< numChannels
; ++i
)
221 zeromem (channels
[i
], size
* sizeof (float));
224 void AudioSampleBuffer::clear (const int startSample
,
225 const int numSamples
) noexcept
227 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
229 for (int i
= 0; i
< numChannels
; ++i
)
230 zeromem (channels
[i
] + startSample
, numSamples
* sizeof (float));
233 void AudioSampleBuffer::clear (const int channel
,
234 const int startSample
,
235 const int numSamples
) noexcept
237 jassert (isPositiveAndBelow (channel
, numChannels
));
238 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
240 zeromem (channels
[channel
] + startSample
, numSamples
* sizeof (float));
243 void AudioSampleBuffer::applyGain (const int channel
,
244 const int startSample
,
246 const float gain
) noexcept
248 jassert (isPositiveAndBelow (channel
, numChannels
));
249 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
253 float* d
= channels
[channel
] + startSample
;
257 zeromem (d
, sizeof (float) * numSamples
);
261 while (--numSamples
>= 0)
267 void AudioSampleBuffer::applyGainRamp (const int channel
,
268 const int startSample
,
271 float endGain
) noexcept
273 if (startGain
== endGain
)
275 applyGain (channel
, startSample
, numSamples
, startGain
);
279 jassert (isPositiveAndBelow (channel
, numChannels
));
280 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
282 const float increment
= (endGain
- startGain
) / numSamples
;
283 float* d
= channels
[channel
] + startSample
;
285 while (--numSamples
>= 0)
288 startGain
+= increment
;
293 void AudioSampleBuffer::applyGain (const int startSample
,
294 const int numSamples
,
295 const float gain
) noexcept
297 for (int i
= 0; i
< numChannels
; ++i
)
298 applyGain (i
, startSample
, numSamples
, gain
);
301 void AudioSampleBuffer::addFrom (const int destChannel
,
302 const int destStartSample
,
303 const AudioSampleBuffer
& source
,
304 const int sourceChannel
,
305 const int sourceStartSample
,
307 const float gain
) noexcept
309 jassert (&source
!= this || sourceChannel
!= destChannel
);
310 jassert (isPositiveAndBelow (destChannel
, numChannels
));
311 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
312 jassert (isPositiveAndBelow (sourceChannel
, source
.numChannels
));
313 jassert (sourceStartSample
>= 0 && sourceStartSample
+ numSamples
<= source
.size
);
315 if (gain
!= 0.0f
&& numSamples
> 0)
317 float* d
= channels
[destChannel
] + destStartSample
;
318 const float* s
= source
.channels
[sourceChannel
] + sourceStartSample
;
322 while (--numSamples
>= 0)
327 while (--numSamples
>= 0)
333 void AudioSampleBuffer::addFrom (const int destChannel
,
334 const int destStartSample
,
337 const float gain
) noexcept
339 jassert (isPositiveAndBelow (destChannel
, numChannels
));
340 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
341 jassert (source
!= nullptr);
343 if (gain
!= 0.0f
&& numSamples
> 0)
345 float* d
= channels
[destChannel
] + destStartSample
;
349 while (--numSamples
>= 0)
350 *d
++ += gain
* *source
++;
354 while (--numSamples
>= 0)
360 void AudioSampleBuffer::addFromWithRamp (const int destChannel
,
361 const int destStartSample
,
365 const float endGain
) noexcept
367 jassert (isPositiveAndBelow (destChannel
, numChannels
));
368 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
369 jassert (source
!= nullptr);
371 if (startGain
== endGain
)
373 addFrom (destChannel
,
381 if (numSamples
> 0 && (startGain
!= 0.0f
|| endGain
!= 0.0f
))
383 const float increment
= (endGain
- startGain
) / numSamples
;
384 float* d
= channels
[destChannel
] + destStartSample
;
386 while (--numSamples
>= 0)
388 *d
++ += startGain
* *source
++;
389 startGain
+= increment
;
395 void AudioSampleBuffer::copyFrom (const int destChannel
,
396 const int destStartSample
,
397 const AudioSampleBuffer
& source
,
398 const int sourceChannel
,
399 const int sourceStartSample
,
400 int numSamples
) noexcept
402 jassert (&source
!= this || sourceChannel
!= destChannel
);
403 jassert (isPositiveAndBelow (destChannel
, numChannels
));
404 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
405 jassert (isPositiveAndBelow (sourceChannel
, source
.numChannels
));
406 jassert (sourceStartSample
>= 0 && sourceStartSample
+ numSamples
<= source
.size
);
410 memcpy (channels
[destChannel
] + destStartSample
,
411 source
.channels
[sourceChannel
] + sourceStartSample
,
412 sizeof (float) * numSamples
);
416 void AudioSampleBuffer::copyFrom (const int destChannel
,
417 const int destStartSample
,
419 int numSamples
) noexcept
421 jassert (isPositiveAndBelow (destChannel
, numChannels
));
422 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
423 jassert (source
!= nullptr);
427 memcpy (channels
[destChannel
] + destStartSample
,
429 sizeof (float) * numSamples
);
433 void AudioSampleBuffer::copyFrom (const int destChannel
,
434 const int destStartSample
,
437 const float gain
) noexcept
439 jassert (isPositiveAndBelow (destChannel
, numChannels
));
440 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
441 jassert (source
!= nullptr);
445 float* d
= channels
[destChannel
] + destStartSample
;
451 zeromem (d
, sizeof (float) * numSamples
);
455 while (--numSamples
>= 0)
456 *d
++ = gain
* *source
++;
461 memcpy (d
, source
, sizeof (float) * numSamples
);
466 void AudioSampleBuffer::copyFromWithRamp (const int destChannel
,
467 const int destStartSample
,
471 float endGain
) noexcept
473 jassert (isPositiveAndBelow (destChannel
, numChannels
));
474 jassert (destStartSample
>= 0 && destStartSample
+ numSamples
<= size
);
475 jassert (source
!= nullptr);
477 if (startGain
== endGain
)
479 copyFrom (destChannel
,
487 if (numSamples
> 0 && (startGain
!= 0.0f
|| endGain
!= 0.0f
))
489 const float increment
= (endGain
- startGain
) / numSamples
;
490 float* d
= channels
[destChannel
] + destStartSample
;
492 while (--numSamples
>= 0)
494 *d
++ = startGain
* *source
++;
495 startGain
+= increment
;
501 void AudioSampleBuffer::findMinMax (const int channel
,
502 const int startSample
,
505 float& maxVal
) const noexcept
507 jassert (isPositiveAndBelow (channel
, numChannels
));
508 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
510 findMinAndMax (channels
[channel
] + startSample
, numSamples
, minVal
, maxVal
);
513 float AudioSampleBuffer::getMagnitude (const int channel
,
514 const int startSample
,
515 const int numSamples
) const noexcept
517 jassert (isPositiveAndBelow (channel
, numChannels
));
518 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
521 findMinMax (channel
, startSample
, numSamples
, mn
, mx
);
523 return jmax (mn
, -mn
, mx
, -mx
);
526 float AudioSampleBuffer::getMagnitude (const int startSample
,
527 const int numSamples
) const noexcept
531 for (int i
= 0; i
< numChannels
; ++i
)
532 mag
= jmax (mag
, getMagnitude (i
, startSample
, numSamples
));
537 float AudioSampleBuffer::getRMSLevel (const int channel
,
538 const int startSample
,
539 const int numSamples
) const noexcept
541 jassert (isPositiveAndBelow (channel
, numChannels
));
542 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
544 if (numSamples
<= 0 || channel
< 0 || channel
>= numChannels
)
547 const float* const data
= channels
[channel
] + startSample
;
550 for (int i
= 0; i
< numSamples
; ++i
)
552 const float sample
= data
[i
];
553 sum
+= sample
* sample
;
556 return (float) std::sqrt (sum
/ numSamples
);
559 void AudioSampleBuffer::readFromAudioReader (AudioFormatReader
* reader
,
560 const int startSample
,
561 const int numSamples
,
562 const int64 readerStartSample
,
563 const bool useLeftChan
,
564 const bool useRightChan
)
566 jassert (reader
!= nullptr);
567 jassert (startSample
>= 0 && startSample
+ numSamples
<= size
);
573 if (useLeftChan
== useRightChan
)
575 chans
[0] = reinterpret_cast<int*> (getSampleData (0, startSample
));
576 chans
[1] = (reader
->numChannels
> 1 && getNumChannels() > 1) ? reinterpret_cast<int*> (getSampleData (1, startSample
)) : 0;
578 else if (useLeftChan
|| (reader
->numChannels
== 1))
580 chans
[0] = reinterpret_cast<int*> (getSampleData (0, startSample
));
583 else if (useRightChan
)
586 chans
[1] = reinterpret_cast<int*> (getSampleData (0, startSample
));
591 reader
->read (chans
, 2, readerStartSample
, numSamples
, true);
593 if (! reader
->usesFloatingPointData
)
595 for (int j
= 0; j
< 2; ++j
)
597 float* const d
= reinterpret_cast <float*> (chans
[j
]);
601 const float multiplier
= 1.0f
/ 0x7fffffff;
603 for (int i
= 0; i
< numSamples
; ++i
)
604 d
[i
] = *reinterpret_cast<int*> (d
+ i
) * multiplier
;
609 if (numChannels
> 1 && (chans
[0] == nullptr || chans
[1] == nullptr))
611 // if this is a stereo buffer and the source was mono, dupe the first channel..
612 memcpy (getSampleData (1, startSample
),
613 getSampleData (0, startSample
),
614 sizeof (float) * numSamples
);
619 void AudioSampleBuffer::writeToAudioWriter (AudioFormatWriter
* writer
,
620 const int startSample
,
621 const int numSamples
) const
623 jassert (writer
!= nullptr);
624 writer
->writeFromAudioSampleBuffer (*this, startSample
, numSamples
);