New Class to handle UI
[juce-lv2.git] / juce / source / src / audio / dsp / juce_AudioSampleBuffer.cpp
blob0b1d5431b2060cb0c4bfad2eb898eab79ae3013b
1 /*
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"
28 BEGIN_JUCE_NAMESPACE
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_),
39 size (numSamples)
41 jassert (numSamples >= 0);
42 jassert (numChannels_ > 0);
44 allocateData();
47 AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept
48 : numChannels (other.numChannels),
49 size (other.size)
51 allocateData();
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)
68 channels[i] = chan;
69 chan += size;
72 channels [numChannels] = 0;
75 AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo,
76 const int numChannels_,
77 const int numSamples) noexcept
78 : numChannels (numChannels_),
79 size (numSamples),
80 allocatedBytes (0)
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_),
91 size (numSamples),
92 allocatedBytes (0)
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);
104 allocatedBytes = 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);
120 else
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
139 if (this != &other)
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);
149 return *this;
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;
190 else
192 if (avoidReallocating && allocatedBytes >= newTotalBytes)
194 if (clearExtraSpace)
195 allocatedData.clear (newTotalBytes);
197 else
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)
207 channels[i] = chan;
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,
245 int numSamples,
246 const float gain) noexcept
248 jassert (isPositiveAndBelow (channel, numChannels));
249 jassert (startSample >= 0 && startSample + numSamples <= size);
251 if (gain != 1.0f)
253 float* d = channels [channel] + startSample;
255 if (gain == 0.0f)
257 zeromem (d, sizeof (float) * numSamples);
259 else
261 while (--numSamples >= 0)
262 *d++ *= gain;
267 void AudioSampleBuffer::applyGainRamp (const int channel,
268 const int startSample,
269 int numSamples,
270 float startGain,
271 float endGain) noexcept
273 if (startGain == endGain)
275 applyGain (channel, startSample, numSamples, startGain);
277 else
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)
287 *d++ *= startGain;
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,
306 int numSamples,
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;
320 if (gain != 1.0f)
322 while (--numSamples >= 0)
323 *d++ += gain * *s++;
325 else
327 while (--numSamples >= 0)
328 *d++ += *s++;
333 void AudioSampleBuffer::addFrom (const int destChannel,
334 const int destStartSample,
335 const float* source,
336 int numSamples,
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;
347 if (gain != 1.0f)
349 while (--numSamples >= 0)
350 *d++ += gain * *source++;
352 else
354 while (--numSamples >= 0)
355 *d++ += *source++;
360 void AudioSampleBuffer::addFromWithRamp (const int destChannel,
361 const int destStartSample,
362 const float* source,
363 int numSamples,
364 float startGain,
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,
374 destStartSample,
375 source,
376 numSamples,
377 startGain);
379 else
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);
408 if (numSamples > 0)
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,
418 const float* source,
419 int numSamples) noexcept
421 jassert (isPositiveAndBelow (destChannel, numChannels));
422 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
423 jassert (source != nullptr);
425 if (numSamples > 0)
427 memcpy (channels [destChannel] + destStartSample,
428 source,
429 sizeof (float) * numSamples);
433 void AudioSampleBuffer::copyFrom (const int destChannel,
434 const int destStartSample,
435 const float* source,
436 int numSamples,
437 const float gain) noexcept
439 jassert (isPositiveAndBelow (destChannel, numChannels));
440 jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
441 jassert (source != nullptr);
443 if (numSamples > 0)
445 float* d = channels [destChannel] + destStartSample;
447 if (gain != 1.0f)
449 if (gain == 0)
451 zeromem (d, sizeof (float) * numSamples);
453 else
455 while (--numSamples >= 0)
456 *d++ = gain * *source++;
459 else
461 memcpy (d, source, sizeof (float) * numSamples);
466 void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
467 const int destStartSample,
468 const float* source,
469 int numSamples,
470 float startGain,
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,
480 destStartSample,
481 source,
482 numSamples,
483 startGain);
485 else
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,
503 int numSamples,
504 float& minVal,
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);
520 float mn, mx;
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
529 float mag = 0.0f;
531 for (int i = 0; i < numChannels; ++i)
532 mag = jmax (mag, getMagnitude (i, startSample, numSamples));
534 return mag;
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)
545 return 0.0f;
547 const float* const data = channels [channel] + startSample;
548 double sum = 0.0;
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);
569 if (numSamples > 0)
571 int* chans[3];
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));
581 chans[1] = nullptr;
583 else if (useRightChan)
585 chans[0] = nullptr;
586 chans[1] = reinterpret_cast<int*> (getSampleData (0, startSample));
589 chans[2] = nullptr;
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]);
599 if (d != nullptr)
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);
627 END_JUCE_NAMESPACE