LMMS
Loading...
Searching...
No Matches
AudioSampleBuffer.h
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017-2022 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
10
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
22
23 ==============================================================================
24*/
25
26#ifndef WATER_AUDIOSAMPLEBUFFER_H_INCLUDED
27#define WATER_AUDIOSAMPLEBUFFER_H_INCLUDED
28
29#include "../memory/HeapBlock.h"
30
31#include "CarlaMathUtils.hpp"
32
33namespace water {
34
35//==============================================================================
42{
43public:
44 //==============================================================================
47 : numChannels(0),
48 size(0),
50 channels(static_cast<float**> (preallocatedChannelSpace)),
53 {
54 }
55
56 //==============================================================================
66 AudioSampleBuffer (const uint32_t numChannelsToAllocate,
67 const uint32_t numSamplesToAllocate,
68 const bool clearData = false) noexcept
69 : numChannels(numChannelsToAllocate),
70 size(numSamplesToAllocate),
72 channels(nullptr),
75 {
76 allocateData (clearData);
77 }
78
94 AudioSampleBuffer (float* const* dataToReferTo,
95 const uint32_t numChannelsToUse,
96 const uint32_t numSamples) noexcept
97 : numChannels(numChannelsToUse),
98 size(numSamples),
100 channels(nullptr),
102 isClear(false)
103 {
104 CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr,);
105
106 allocateChannels (dataToReferTo, 0);
107 }
108
125 AudioSampleBuffer (float* const* dataToReferTo,
126 const uint32_t numChannelsToUse,
127 const uint32_t startSample,
128 const uint32_t numSamples) noexcept
129 : numChannels(numChannelsToUse),
130 size(numSamples),
132 channels(nullptr),
134 isClear(false)
135 {
136 CARLA_SAFE_ASSERT_RETURN (dataToReferTo != nullptr,);
137
138 allocateChannels (dataToReferTo, startSample);
139 }
140
148 : numChannels(other.numChannels),
149 size(other.size),
150 allocatedBytes(other.allocatedBytes),
151 channels(nullptr),
153 isClear(false)
154 {
155 if (allocatedBytes == 0)
156 {
157 allocateChannels (other.channels, 0);
158 }
159 else
160 {
161 allocateData();
162
163 if (other.isClear)
164 {
165 clear();
166 }
167 else
168 {
169 for (uint32_t i = 0; i < numChannels; ++i)
170 carla_copyFloats (channels[i], other.channels[i], size);
171 }
172 }
173 }
174
176 {
177 numChannels = other.numChannels;
178 size = other.size;
179 allocatedBytes = other.allocatedBytes;
180 channels = other.channels;
181
182 if (allocatedBytes == 0)
183 {
184 allocateChannels (other.channels, 0);
185 }
186 else
187 {
188 allocateData();
189
190 if (other.isClear)
191 {
192 clear();
193 }
194 else
195 {
196 for (uint32_t i = 0; i < numChannels; ++i)
197 carla_copyFloats (channels[i], other.channels[i], size);
198 }
199 }
200 return *this;
201 }
202
207
208 //==============================================================================
213
218
226 const float* getReadPointer (const uint32_t channelNumber) const noexcept
227 {
228 CARLA_SAFE_ASSERT_RETURN (channelNumber < numChannels, nullptr);
229
230 return channels [channelNumber];
231 }
232
240 const float* getReadPointer (const uint32_t channelNumber, const uint32_t sampleIndex) const noexcept
241 {
242 CARLA_SAFE_ASSERT_RETURN (channelNumber < numChannels, nullptr);
243 CARLA_SAFE_ASSERT_RETURN (sampleIndex < size, nullptr);
244
245 return channels [channelNumber] + sampleIndex;
246 }
247
254 float* getWritePointer (const uint32_t channelNumber) noexcept
255 {
256 CARLA_SAFE_ASSERT_RETURN (channelNumber < numChannels, nullptr);
257
258 isClear = false;
259 return channels [channelNumber];
260 }
261
268 float* getWritePointer (const uint32_t channelNumber, const uint32_t sampleIndex) noexcept
269 {
270 CARLA_SAFE_ASSERT_RETURN (channelNumber < numChannels, nullptr);
271 CARLA_SAFE_ASSERT_RETURN (sampleIndex < size, nullptr);
272
273 isClear = false;
274 return channels [channelNumber] + sampleIndex;
275 }
276
282 const float** getArrayOfReadPointers() const noexcept { return const_cast<const float**> (channels); }
283
289 float** getArrayOfWritePointers() noexcept { isClear = false; return channels; }
290
291 //==============================================================================
296 bool setSize (const uint32_t newNumChannels, const uint32_t newNumSamples) noexcept
297 {
298 if (newNumSamples != size || newNumChannels != numChannels)
299 {
300 const uint32_t allocatedSamplesPerChannel = (newNumSamples + 3) & ~3u;
301 const uint32_t channelListSize = ((sizeof (float*) * (newNumChannels + 1)) + 15) & ~15u;
302 const size_t newTotalBytes = newNumChannels * allocatedSamplesPerChannel * sizeof(float) + channelListSize + 32u;
303
304 if (allocatedBytes >= newTotalBytes)
305 {
306 if (isClear)
307 allocatedData.clear (newTotalBytes);
308 }
309 else
310 {
311 CARLA_SAFE_ASSERT_RETURN (allocatedData.allocate (newTotalBytes, isClear), false);
312 allocatedBytes = newTotalBytes;
313 channels = reinterpret_cast<float**> (allocatedData.getData());
314 }
315
316 float* chan = reinterpret_cast<float*> (allocatedData + channelListSize);
317 for (uint32_t i = 0; i < newNumChannels; ++i)
318 {
319 channels[i] = chan;
320 chan += allocatedSamplesPerChannel;
321 }
322
323 channels [newNumChannels] = nullptr;
324 size = newNumSamples;
325 numChannels = newNumChannels;
326 }
327
328 return true;
329 }
330
331 //==============================================================================
336 bool setSizeRT (const uint32_t newNumSamples) noexcept
337 {
338 if (newNumSamples != size)
339 {
340 const uint32_t allocatedSamplesPerChannel = (newNumSamples + 3) & ~3u;
341 const uint32_t channelListSize = ((sizeof (float*) * (numChannels + 1)) + 15) & ~15u;
342 const size_t newTotalBytes = numChannels * allocatedSamplesPerChannel * sizeof(float) + channelListSize + 32u;
343
344 CARLA_SAFE_ASSERT_RETURN(allocatedBytes >= newTotalBytes, false);
345
346 float* chan = reinterpret_cast<float*> (allocatedData + channelListSize);
347 for (uint32_t i = 0; i < numChannels; ++i)
348 {
349 channels[i] = chan;
350 chan += allocatedSamplesPerChannel;
351 }
352
353 size = newNumSamples;
354 }
355
356 return true;
357 }
358
377 bool setDataToReferTo (float** dataToReferTo,
378 const uint32_t newNumChannels,
379 const uint32_t newNumSamples) noexcept
380 {
381 CARLA_SAFE_ASSERT_RETURN(dataToReferTo != nullptr, false);
382
383 if (allocatedBytes != 0)
384 {
385 allocatedBytes = 0;
386 allocatedData.free();
387 }
388
389 numChannels = newNumChannels;
390 size = newNumSamples;
391
392 return allocateChannels (dataToReferTo, 0);
393 }
394
395 //==============================================================================
398 {
399 if (! isClear)
400 {
401 for (uint32_t i = 0; i < numChannels; ++i)
402 carla_zeroFloats (channels[i], size);
403
404 isClear = true;
405 }
406 }
407
413 void clear (const uint32_t startSample,
414 const uint32_t numSamples) noexcept
415 {
416 CARLA_SAFE_ASSERT_UINT2_RETURN(startSample + numSamples <= size, numSamples, size,);
417
418 if (! isClear)
419 {
420 if (startSample == 0 && numSamples == size)
421 isClear = true;
422
423 for (uint32_t i = 0; i < numChannels; ++i)
424 carla_zeroFloats (channels[i] + startSample, numSamples);
425 }
426 }
427
433 void clear (const uint32_t channel,
434 const uint32_t startSample,
435 const uint32_t numSamples) noexcept
436 {
438 CARLA_SAFE_ASSERT_UINT2_RETURN(startSample + numSamples <= size, numSamples, size,);
439
440 if (! isClear)
441 carla_zeroFloats (channels [channel] + startSample, numSamples);
442 }
443
451
452 //==============================================================================
466 void addFrom (const uint32_t destChannel,
467 const uint32_t destStartSample,
468 const AudioSampleBuffer& source,
469 const uint32_t sourceChannel,
470 const uint32_t sourceStartSample,
471 const uint32_t numSamples,
472 const float gainToApplyToSource = 1.0f) noexcept
473 {
474 CARLA_SAFE_ASSERT_UINT2_RETURN(&source != this || sourceChannel != destChannel, sourceChannel, destChannel,);
475 CARLA_SAFE_ASSERT_UINT2_RETURN(destChannel < numChannels, destChannel, numChannels,);
476 CARLA_SAFE_ASSERT_UINT2_RETURN(sourceChannel < source.numChannels, sourceChannel, source.numChannels,);
477 CARLA_SAFE_ASSERT_UINT2_RETURN(destStartSample + numSamples <= size, numSamples, size,);
478 CARLA_SAFE_ASSERT_UINT2_RETURN(sourceStartSample + numSamples <= source.size, numSamples, source.size,);
479
480 if (carla_isNotZero(gainToApplyToSource) && numSamples != 0 && ! source.isClear)
481 {
482 float* const d = channels [destChannel] + destStartSample;
483 const float* const s = source.channels [sourceChannel] + sourceStartSample;
484
485 if (isClear)
486 {
487 isClear = false;
488
489 if (carla_isNotZero(gainToApplyToSource - 1.0f))
490 carla_copyWithMultiply (d, s, gainToApplyToSource, numSamples);
491 else
492 carla_copyFloats (d, s, numSamples);
493 }
494 else
495 {
496 if (carla_isNotZero(gainToApplyToSource - 1.0f))
497 carla_addWithMultiply (d, s, gainToApplyToSource, numSamples);
498 else
499 carla_add (d, s, numSamples);
500 }
501 }
502 }
503
504
516 void addFrom (const uint32_t destChannel,
517 const uint32_t destStartSample,
518 const float* source,
519 const uint32_t numSamples,
520 float gainToApplyToSource = 1.0f) noexcept
521 {
522 CARLA_SAFE_ASSERT_UINT2_RETURN(destChannel < numChannels, destChannel, numChannels,);
523 CARLA_SAFE_ASSERT_UINT2_RETURN(destStartSample + numSamples <= size, numSamples, size,);
524 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
525
526 if (carla_isNotZero(gainToApplyToSource) && numSamples != 0)
527 {
528 float* const d = channels [destChannel] + destStartSample;
529
530 if (isClear)
531 {
532 isClear = false;
533
534 if (carla_isNotZero(gainToApplyToSource - 1.0f))
535 carla_copyWithMultiply (d, source, gainToApplyToSource, numSamples);
536 else
537 carla_copyFloats (d, source, numSamples);
538 }
539 else
540 {
541 if (carla_isNotZero(gainToApplyToSource - 1.0f))
542 carla_addWithMultiply (d, source, gainToApplyToSource, numSamples);
543 else
544 carla_add (d, source, numSamples);
545 }
546 }
547 }
548
560 void copyFrom (const uint32_t destChannel,
561 const uint32_t destStartSample,
562 const AudioSampleBuffer& source,
563 const uint32_t sourceChannel,
564 const uint32_t sourceStartSample,
565 const uint32_t numSamples) noexcept
566 {
567 CARLA_SAFE_ASSERT_UINT2_RETURN(&source != this || sourceChannel != destChannel, sourceChannel, destChannel,);
568 CARLA_SAFE_ASSERT_UINT2_RETURN(destChannel < numChannels, destChannel, numChannels,);
569 CARLA_SAFE_ASSERT_UINT2_RETURN(sourceChannel < source.numChannels, sourceChannel, source.numChannels,);
570 CARLA_SAFE_ASSERT_UINT2_RETURN(destStartSample + numSamples <= size, numSamples, size,);
571 CARLA_SAFE_ASSERT_UINT2_RETURN(sourceStartSample + numSamples <= source.size, numSamples, source.size,);
572
573 if (numSamples > 0)
574 {
575 if (source.isClear)
576 {
577 if (! isClear)
578 carla_zeroFloats (channels [destChannel] + destStartSample, numSamples);
579 }
580 else
581 {
582 isClear = false;
583 carla_copyFloats (channels [destChannel] + destStartSample,
584 source.channels [sourceChannel] + sourceStartSample,
585 numSamples);
586 }
587 }
588 }
589
599 void copyFrom (const uint32_t destChannel,
600 const uint32_t destStartSample,
601 const float* source,
602 const uint32_t numSamples) noexcept
603 {
604 CARLA_SAFE_ASSERT_UINT2_RETURN(destChannel < numChannels, destChannel, numChannels,);
605 CARLA_SAFE_ASSERT_UINT2_RETURN(destStartSample + numSamples <= size, numSamples, size,);
606 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
607
608 if (numSamples > 0)
609 {
610 isClear = false;
611 carla_copyFloats (channels [destChannel] + destStartSample, source, numSamples);
612 }
613 }
614
625 void copyFrom (const uint32_t destChannel,
626 const uint32_t destStartSample,
627 const float* source,
628 const uint32_t numSamples,
629 float gain) noexcept
630 {
631 CARLA_SAFE_ASSERT_UINT2_RETURN(destChannel < numChannels, destChannel, numChannels,);
632 CARLA_SAFE_ASSERT_UINT2_RETURN(destStartSample + numSamples <= size, numSamples, size,);
633 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
634
635 if (numSamples > 0)
636 {
637 float* const d = channels [destChannel] + destStartSample;
638
639 if (carla_isZero(gain))
640 {
641 if (! isClear)
642 carla_zeroFloats (d, numSamples);
643 }
644 else if (carla_isZero(gain - 1.0f))
645 {
646 isClear = false;
647 carla_copyFloats (d, source, numSamples);
648 }
649 else
650 {
651 isClear = false;
652 carla_copyWithMultiply (d, source, gain, numSamples);
653 }
654 }
655 }
656
666 void copyFromInterleavedSource (const uint32_t destChannel,
667 const float* source,
668 const uint32_t totalNumSamples) noexcept
669 {
671 CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
672
673 if (const uint32_t numSamples = totalNumSamples / numChannels)
674 {
675 CARLA_SAFE_ASSERT_RETURN(numSamples <= size,);
676
677 isClear = false;
678 float* d = channels [destChannel];
679
680 for (uint32_t i=0; i < numSamples; ++i)
681 d[i] = source[i * numChannels + destChannel];
682 }
683 }
684
685private:
686 //==============================================================================
689 float** channels;
693
694 bool allocateData (bool clearData = false)
695 {
696 const size_t channelListSize = sizeof (float*) * (numChannels + 1);
697 const size_t nextAllocatedBytes = numChannels * size * sizeof (float) + channelListSize + 32;
698 CARLA_SAFE_ASSERT_RETURN (allocatedData.allocate (nextAllocatedBytes, clearData), false);
699
700 allocatedBytes = nextAllocatedBytes;
701 channels = reinterpret_cast<float**> (allocatedData.getData());
702
703 float* chan = (float*) (allocatedData + channelListSize);
704 for (uint32_t i = 0; i < numChannels; ++i)
705 {
706 channels[i] = chan;
707 chan += size;
708 }
709
710 channels [numChannels] = nullptr;
711 isClear = clearData;
712 return true;
713 }
714
715 bool allocateChannels (float* const* const dataToReferTo, const uint32_t offset)
716 {
717 // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
719 {
720 channels = static_cast<float**> (preallocatedChannelSpace);
721 }
722 else
723 {
724 CARLA_SAFE_ASSERT_RETURN( allocatedData.malloc (numChannels + 1, sizeof (float*)), false);
725 channels = reinterpret_cast<float**> (allocatedData.getData());
726 }
727
728 for (uint32_t i = 0; i < numChannels; ++i)
729 {
730 // you have to pass in the same number of valid pointers as numChannels
731 CARLA_SAFE_ASSERT_CONTINUE (dataToReferTo[i] != nullptr);
732
733 channels[i] = dataToReferTo[i] + offset;
734 }
735
736 channels [numChannels] = nullptr;
737 isClear = false;
738 return true;
739 }
740
741 // CARLA_DECLARE_NON_COPYABLE(AudioSampleBuffer)
742};
743
744}
745
746#endif // WATER_AUDIOSAMPLEBUFFER_H_INCLUDED
#define CARLA_SAFE_ASSERT_CONTINUE(cond)
Definition CarlaDefines.h:189
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
#define CARLA_SAFE_ASSERT_UINT2_RETURN(cond, v1, v2, ret)
Definition CarlaDefines.h:215
#define noexcept
Definition DistrhoDefines.h:72
AudioSampleBuffer() noexcept
Definition AudioSampleBuffer.h:46
AudioSampleBuffer & operator=(const AudioSampleBuffer &other) noexcept
Definition AudioSampleBuffer.h:175
uint32_t size
Definition AudioSampleBuffer.h:687
bool hasBeenCleared() const noexcept
Definition AudioSampleBuffer.h:450
uint32_t getNumSamples() const noexcept
Definition AudioSampleBuffer.h:217
uint32_t getNumChannels() const noexcept
Definition AudioSampleBuffer.h:212
bool allocateChannels(float *const *const dataToReferTo, const uint32_t offset)
Definition AudioSampleBuffer.h:715
void addFrom(const uint32_t destChannel, const uint32_t destStartSample, const float *source, const uint32_t numSamples, float gainToApplyToSource=1.0f) noexcept
Definition AudioSampleBuffer.h:516
float ** channels
Definition AudioSampleBuffer.h:689
void addFrom(const uint32_t destChannel, const uint32_t destStartSample, const AudioSampleBuffer &source, const uint32_t sourceChannel, const uint32_t sourceStartSample, const uint32_t numSamples, const float gainToApplyToSource=1.0f) noexcept
Definition AudioSampleBuffer.h:466
bool setSize(const uint32_t newNumChannels, const uint32_t newNumSamples) noexcept
Definition AudioSampleBuffer.h:296
void clear(const uint32_t channel, const uint32_t startSample, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:433
void copyFrom(const uint32_t destChannel, const uint32_t destStartSample, const float *source, const uint32_t numSamples, float gain) noexcept
Definition AudioSampleBuffer.h:625
AudioSampleBuffer(float *const *dataToReferTo, const uint32_t numChannelsToUse, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:94
AudioSampleBuffer() noexcept
Definition AudioSampleBuffer.h:46
const float * getReadPointer(const uint32_t channelNumber, const uint32_t sampleIndex) const noexcept
Definition AudioSampleBuffer.h:240
bool setSizeRT(const uint32_t newNumSamples) noexcept
Definition AudioSampleBuffer.h:336
float ** getArrayOfWritePointers() noexcept
Definition AudioSampleBuffer.h:289
uint32_t numChannels
Definition AudioSampleBuffer.h:687
bool isClear
Definition AudioSampleBuffer.h:692
AudioSampleBuffer(float *const *dataToReferTo, const uint32_t numChannelsToUse, const uint32_t startSample, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:125
~AudioSampleBuffer() noexcept
Definition AudioSampleBuffer.h:206
void copyFrom(const uint32_t destChannel, const uint32_t destStartSample, const AudioSampleBuffer &source, const uint32_t sourceChannel, const uint32_t sourceStartSample, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:560
HeapBlock< char > allocatedData
Definition AudioSampleBuffer.h:690
bool allocateData(bool clearData=false)
Definition AudioSampleBuffer.h:694
float * preallocatedChannelSpace[32]
Definition AudioSampleBuffer.h:691
size_t allocatedBytes
Definition AudioSampleBuffer.h:688
bool setDataToReferTo(float **dataToReferTo, const uint32_t newNumChannels, const uint32_t newNumSamples) noexcept
Definition AudioSampleBuffer.h:377
float * getWritePointer(const uint32_t channelNumber) noexcept
Definition AudioSampleBuffer.h:254
void copyFromInterleavedSource(const uint32_t destChannel, const float *source, const uint32_t totalNumSamples) noexcept
Definition AudioSampleBuffer.h:666
void copyFrom(const uint32_t destChannel, const uint32_t destStartSample, const float *source, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:599
float * getWritePointer(const uint32_t channelNumber, const uint32_t sampleIndex) noexcept
Definition AudioSampleBuffer.h:268
void clear() noexcept
Definition AudioSampleBuffer.h:397
AudioSampleBuffer(const uint32_t numChannelsToAllocate, const uint32_t numSamplesToAllocate, const bool clearData=false) noexcept
Definition AudioSampleBuffer.h:66
const float * getReadPointer(const uint32_t channelNumber) const noexcept
Definition AudioSampleBuffer.h:226
const float ** getArrayOfReadPointers() const noexcept
Definition AudioSampleBuffer.h:282
AudioSampleBuffer(const AudioSampleBuffer &other) noexcept
Definition AudioSampleBuffer.h:147
void clear(const uint32_t startSample, const uint32_t numSamples) noexcept
Definition AudioSampleBuffer.h:413
Definition HeapBlock.h:77
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned int uint32_t
Definition mid.cpp:100
Definition AudioSampleBuffer.h:33
size_t numElementsInArray(Type(&array)[N])
Definition MathsFunctions.h:257
#define false
Definition ordinals.h:83
#define const
Definition zconf.h:137