VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_dsp / containers / juce_AudioBlock.h
blob58e1a32769fbfb6ceb63f1052e03705d99edc403
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
23 ==============================================================================
26 namespace juce
28 namespace dsp
31 #ifndef DOXYGEN
32 namespace SampleTypeHelpers // Internal classes needed for handling sample type classes
34 template <typename T, bool = std::is_floating_point<T>::value>
35 struct ElementType
37 using Type = T;
40 template <typename T>
41 struct ElementType<const T, false>
43 using Type = const typename T::value_type;
46 template <typename T>
47 struct ElementType<T, false>
49 using Type = typename T::value_type;
52 #endif
54 //==============================================================================
55 /**
56 Minimal and lightweight data-structure which contains a list of pointers to
57 channels containing some kind of sample data.
59 This class doesn't own any of the data which it points to, it's simply a view
60 into data that is owned elsewhere. You can construct one from some raw data
61 that you've allocated yourself, or give it a HeapBlock to use, or give it
62 an AudioBuffer which it can refer to, but in all cases the user is
63 responsible for making sure that the data doesn't get deleted while there's
64 still an AudioBlock using it.
66 @tags{DSP}
68 template <typename SampleType>
69 class AudioBlock
71 private:
72 template <typename OtherSampleType>
73 using MayUseConvertingConstructor =
74 std::enable_if_t<std::is_same<std::remove_const_t<SampleType>,
75 std::remove_const_t<OtherSampleType>>::value
76 && std::is_const<SampleType>::value
77 && ! std::is_const<OtherSampleType>::value,
78 int>;
80 public:
81 //==============================================================================
82 using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
84 //==============================================================================
85 /** Create a zero-sized AudioBlock. */
86 AudioBlock() noexcept = default;
88 /** Creates an AudioBlock from a pointer to an array of channels.
89 AudioBlock does not copy nor own the memory pointed to by dataToUse.
90 Therefore it is the user's responsibility to ensure that the memory is retained
91 throughout the life-time of the AudioBlock and released when no longer needed.
93 constexpr AudioBlock (SampleType* const* channelData,
94 size_t numberOfChannels, size_t numberOfSamples) noexcept
95 : channels (channelData),
96 numChannels (static_cast<ChannelCountType> (numberOfChannels)),
97 numSamples (numberOfSamples)
101 /** Creates an AudioBlock from a pointer to an array of channels.
102 AudioBlock does not copy nor own the memory pointed to by dataToUse.
103 Therefore it is the user's responsibility to ensure that the memory is retained
104 throughout the life-time of the AudioBlock and released when no longer needed.
106 constexpr AudioBlock (SampleType* const* channelData, size_t numberOfChannels,
107 size_t startSampleIndex, size_t numberOfSamples) noexcept
108 : channels (channelData),
109 numChannels (static_cast<ChannelCountType> (numberOfChannels)),
110 startSample (startSampleIndex),
111 numSamples (numberOfSamples)
115 /** Allocates a suitable amount of space in a HeapBlock, and initialises this object
116 to point into it.
117 The HeapBlock must of course not be freed or re-allocated while this object is still in
118 use, because it will be referencing its data.
120 AudioBlock (HeapBlock<char>& heapBlockToUseForAllocation,
121 size_t numberOfChannels, size_t numberOfSamples,
122 size_t alignmentInBytes = defaultAlignment) noexcept
123 : numChannels (static_cast<ChannelCountType> (numberOfChannels)),
124 numSamples (numberOfSamples)
126 auto roundedUpNumSamples = (numberOfSamples + elementMask) & ~elementMask;
127 auto channelSize = sizeof (SampleType) * roundedUpNumSamples;
128 auto channelListBytes = sizeof (SampleType*) * numberOfChannels;
129 auto extraBytes = alignmentInBytes - 1;
131 heapBlockToUseForAllocation.malloc (channelListBytes + extraBytes + channelSize * numberOfChannels);
133 auto* chanArray = unalignedPointerCast<SampleType**> (heapBlockToUseForAllocation.getData());
134 channels = chanArray;
136 auto* data = unalignedPointerCast<SampleType*> (addBytesToPointer (chanArray, channelListBytes));
137 data = snapPointerToAlignment (data, alignmentInBytes);
139 for (ChannelCountType i = 0; i < numChannels; ++i)
141 chanArray[i] = data;
142 data += roundedUpNumSamples;
146 /** Creates an AudioBlock that points to the data in an AudioBuffer.
147 AudioBlock does not copy nor own the memory pointed to by dataToUse.
148 Therefore it is the user's responsibility to ensure that the buffer is retained
149 throughout the life-time of the AudioBlock without being modified.
151 template <typename OtherSampleType>
152 constexpr AudioBlock (AudioBuffer<OtherSampleType>& buffer) noexcept
153 : channels (buffer.getArrayOfWritePointers()),
154 numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())),
155 numSamples (static_cast<size_t> (buffer.getNumSamples()))
159 /** Creates an AudioBlock that points to the data in an AudioBuffer.
160 AudioBlock does not copy nor own the memory pointed to by dataToUse.
161 Therefore it is the user's responsibility to ensure that the buffer is retained
162 throughout the life-time of the AudioBlock without being modified.
164 template <typename OtherSampleType>
165 constexpr AudioBlock (const AudioBuffer<OtherSampleType>& buffer) noexcept
166 : channels (buffer.getArrayOfReadPointers()),
167 numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())),
168 numSamples (static_cast<size_t> (buffer.getNumSamples()))
172 /** Creates an AudioBlock that points to the data in an AudioBuffer.
173 AudioBlock does not copy nor own the memory pointed to by dataToUse.
174 Therefore it is the user's responsibility to ensure that the buffer is retained
175 throughout the life-time of the AudioBlock without being modified.
177 template <typename OtherSampleType>
178 AudioBlock (AudioBuffer<OtherSampleType>& buffer, size_t startSampleIndex) noexcept
179 : channels (buffer.getArrayOfWritePointers()),
180 numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())),
181 startSample (startSampleIndex),
182 numSamples (static_cast<size_t> (buffer.getNumSamples()) - startSampleIndex)
184 jassert (startSample < static_cast<size_t> (buffer.getNumSamples()));
187 AudioBlock (const AudioBlock& other) noexcept = default;
188 AudioBlock& operator= (const AudioBlock& other) noexcept = default;
190 template <typename OtherSampleType, MayUseConvertingConstructor<OtherSampleType> = 0>
191 AudioBlock (const AudioBlock<OtherSampleType>& other) noexcept
192 : channels { other.channels },
193 numChannels { other.numChannels },
194 startSample { other.startSample },
195 numSamples { other.numSamples }
199 template <typename OtherSampleType, MayUseConvertingConstructor<OtherSampleType> = 0>
200 AudioBlock& operator= (const AudioBlock<OtherSampleType>& other) noexcept
202 AudioBlock blockCopy { other };
203 swap (blockCopy);
204 return *this;
207 void swap (AudioBlock& other) noexcept
209 std::swap (other.channels, channels);
210 std::swap (other.numChannels, numChannels);
211 std::swap (other.startSample, startSample);
212 std::swap (other.numSamples, numSamples);
215 //==============================================================================
216 template <typename OtherSampleType>
217 constexpr bool operator== (const AudioBlock<OtherSampleType>& other) const noexcept
219 return std::equal (channels,
220 channels + numChannels,
221 other.channels,
222 other.channels + other.numChannels)
223 && startSample == other.startSample
224 && numSamples == other.numSamples;
227 template <typename OtherSampleType>
228 constexpr bool operator!= (const AudioBlock<OtherSampleType>& other) const noexcept
230 return ! (*this == other);
233 //==============================================================================
234 /** Returns the number of channels referenced by this block. */
235 constexpr size_t getNumChannels() const noexcept { return static_cast<size_t> (numChannels); }
237 /** Returns the number of samples referenced by this block. */
238 constexpr size_t getNumSamples() const noexcept { return numSamples; }
240 /** Returns a raw pointer into one of the channels in this block. */
241 SampleType* getChannelPointer (size_t channel) const noexcept
243 jassert (channel < numChannels);
244 jassert (numSamples > 0);
245 return channels[channel] + startSample;
248 /** Returns an AudioBlock that represents one of the channels in this block. */
249 AudioBlock getSingleChannelBlock (size_t channel) const noexcept
251 jassert (channel < numChannels);
252 return AudioBlock (channels + channel, 1, startSample, numSamples);
255 /** Returns a subset of contiguous channels
256 @param channelStart First channel of the subset
257 @param numChannelsToUse Count of channels in the subset
259 AudioBlock getSubsetChannelBlock (size_t channelStart, size_t numChannelsToUse) const noexcept
261 jassert (channelStart < numChannels);
262 jassert ((channelStart + numChannelsToUse) <= numChannels);
264 return AudioBlock (channels + channelStart, numChannelsToUse, startSample, numSamples);
267 /** Returns a sample from the buffer.
268 The channel and index are not checked - they are expected to be in-range. If not,
269 an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
270 territory.
272 SampleType getSample (int channel, int sampleIndex) const noexcept
274 jassert (isPositiveAndBelow (channel, numChannels));
275 jassert (isPositiveAndBelow (sampleIndex, numSamples));
276 return channels[channel][(size_t) startSample + (size_t) sampleIndex];
279 /** Modifies a sample in the buffer.
280 The channel and index are not checked - they are expected to be in-range. If not,
281 an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
282 territory.
284 void setSample (int destChannel, int destSample, SampleType newValue) const noexcept
286 jassert (isPositiveAndBelow (destChannel, numChannels));
287 jassert (isPositiveAndBelow (destSample, numSamples));
288 channels[destChannel][(size_t) startSample + (size_t) destSample] = newValue;
291 /** Adds a value to a sample in the buffer.
292 The channel and index are not checked - they are expected to be in-range. If not,
293 an assertion will be thrown, but in a release build, you're into 'undefined behaviour'
294 territory.
296 void addSample (int destChannel, int destSample, SampleType valueToAdd) const noexcept
298 jassert (isPositiveAndBelow (destChannel, numChannels));
299 jassert (isPositiveAndBelow (destSample, numSamples));
300 channels[destChannel][(size_t) startSample + (size_t) destSample] += valueToAdd;
303 //==============================================================================
304 /** Clears the memory referenced by this AudioBlock. */
305 AudioBlock& clear() noexcept { clearInternal(); return *this; }
306 const AudioBlock& clear() const noexcept { clearInternal(); return *this; }
308 /** Fills the memory referenced by this AudioBlock with value. */
309 AudioBlock& JUCE_VECTOR_CALLTYPE fill (NumericType value) noexcept { fillInternal (value); return *this; }
310 const AudioBlock& JUCE_VECTOR_CALLTYPE fill (NumericType value) const noexcept { fillInternal (value); return *this; }
312 /** Copies the values in src to this block. */
313 template <typename OtherSampleType>
314 AudioBlock& copyFrom (const AudioBlock<OtherSampleType>& src) noexcept { copyFromInternal (src); return *this; }
315 template <typename OtherSampleType>
316 const AudioBlock& copyFrom (const AudioBlock<OtherSampleType>& src) const noexcept { copyFromInternal (src); return *this; }
318 /** Copy the values from an AudioBuffer to this block.
320 All indices and sizes are in this AudioBlock's units, i.e. if SampleType is a
321 SIMDRegister then incrementing srcPos by one will increase the sample position
322 in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.
324 template <typename OtherNumericType>
325 AudioBlock& copyFrom (const AudioBuffer<OtherNumericType>& src,
326 size_t srcPos = 0, size_t dstPos = 0,
327 size_t numElements = std::numeric_limits<size_t>::max()) { copyFromInternal (src, srcPos, dstPos, numElements); return *this; }
328 template <typename OtherNumericType>
329 const AudioBlock& copyFrom (const AudioBuffer<OtherNumericType>& src,
330 size_t srcPos = 0, size_t dstPos = 0,
331 size_t numElements = std::numeric_limits<size_t>::max()) const { copyFromInternal (src, srcPos, dstPos, numElements); return *this; }
334 /** Copies the values from this block to an AudioBuffer.
336 All indices and sizes are in this AudioBlock's units, i.e. if SampleType is a
337 SIMDRegister then incrementing dstPos by one will increase the sample position
338 in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.
340 void copyTo (AudioBuffer<typename std::remove_const<NumericType>::type>& dst, size_t srcPos = 0, size_t dstPos = 0,
341 size_t numElements = std::numeric_limits<size_t>::max()) const
343 auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;
344 auto n = jmin (numSamples - srcPos, dstlen - dstPos, numElements) * sizeFactor;
345 auto maxChannels = jmin (static_cast<size_t> (dst.getNumChannels()), static_cast<size_t> (numChannels));
347 for (size_t ch = 0; ch < maxChannels; ++ch)
348 FloatVectorOperations::copy (dst.getWritePointer ((int) ch, (int) (dstPos * sizeFactor)),
349 getDataPointer (ch) + (srcPos * sizeFactor),
353 /** Move memory within this block from the position srcPos to the position dstPos.
354 If numElements is not specified then move will move the maximum amount of memory.
356 AudioBlock& move (size_t srcPos, size_t dstPos,
357 size_t numElements = std::numeric_limits<size_t>::max()) noexcept { moveInternal (srcPos, dstPos, numElements); return *this; }
358 const AudioBlock& move (size_t srcPos, size_t dstPos,
359 size_t numElements = std::numeric_limits<size_t>::max()) const noexcept { moveInternal (srcPos, dstPos, numElements); return *this; }
361 //==============================================================================
362 /** Return a new AudioBlock pointing to a sub-block inside this block. This
363 function does not copy the memory and you must ensure that the original memory
364 pointed to by the receiver remains valid through-out the life-time of the
365 returned sub-block.
367 @param newOffset The index of an element inside the receiver which will
368 will become the first element of the return value.
369 @param newLength The number of elements of the newly created sub-block.
371 AudioBlock getSubBlock (size_t newOffset, size_t newLength) const noexcept
373 jassert (newOffset < numSamples);
374 jassert (newOffset + newLength <= numSamples);
376 return AudioBlock (channels, numChannels, startSample + newOffset, newLength);
379 /** Return a new AudioBlock pointing to a sub-block inside this block. This
380 function does not copy the memory and you must ensure that the original memory
381 pointed to by the receiver remains valid through-out the life-time of the
382 returned sub-block.
384 @param newOffset The index of an element inside the block which will
385 will become the first element of the return value.
386 The return value will include all subsequent elements
387 of the receiver.
389 AudioBlock getSubBlock (size_t newOffset) const noexcept
391 return getSubBlock (newOffset, getNumSamples() - newOffset);
394 //==============================================================================
395 /** Adds a fixed value to the elements in this block. */
396 AudioBlock& JUCE_VECTOR_CALLTYPE add (NumericType value) noexcept { addInternal (value); return *this; }
397 const AudioBlock& JUCE_VECTOR_CALLTYPE add (NumericType value) const noexcept { addInternal (value); return *this; }
399 /** Adds the elements in the src block to the elements in this block. */
400 template <typename OtherSampleType>
401 AudioBlock& add (AudioBlock<OtherSampleType> src) noexcept { addInternal (src); return *this; }
402 template <typename OtherSampleType>
403 const AudioBlock& add (AudioBlock<OtherSampleType> src) const noexcept { addInternal (src); return *this; }
405 /** Adds a fixed value to each source value and replaces the contents of this block. */
406 template <typename OtherSampleType>
407 AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, NumericType value) noexcept { replaceWithSumOfInternal (src, value); return *this; }
408 template <typename OtherSampleType>
409 const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithSumOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept { replaceWithSumOfInternal (src, value); return *this; }
411 /** Adds each source1 value to the corresponding source2 value and replaces the contents of this block. */
412 template <typename Src1SampleType, typename Src2SampleType>
413 AudioBlock& replaceWithSumOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { replaceWithSumOfInternal (src1, src2); return *this; }
414 template <typename Src1SampleType, typename Src2SampleType>
415 const AudioBlock& replaceWithSumOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { replaceWithSumOfInternal (src1, src2); return *this; }
417 //==============================================================================
418 /** Subtracts a fixed value from the elements in this block. */
419 AudioBlock& JUCE_VECTOR_CALLTYPE subtract (NumericType value) noexcept { subtractInternal (value); return *this; }
420 const AudioBlock& JUCE_VECTOR_CALLTYPE subtract (NumericType value) const noexcept { subtractInternal (value); return *this; }
422 /** Subtracts the source values from the elements in this block. */
423 template <typename OtherSampleType>
424 AudioBlock& subtract (AudioBlock<OtherSampleType> src) noexcept { subtractInternal (src); return *this; }
425 template <typename OtherSampleType>
426 const AudioBlock& subtract (AudioBlock<OtherSampleType> src) const noexcept { subtractInternal (src); return *this; }
428 /** Subtracts a fixed value from each source value and replaces the contents of this block. */
429 template <typename OtherSampleType>
430 AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, NumericType value) noexcept { replaceWithDifferenceOfInternal (src, value); return *this; }
431 template <typename OtherSampleType>
432 const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithDifferenceOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept { replaceWithDifferenceOfInternal (src, value); return *this; }
434 /** Subtracts each source2 value from the corresponding source1 value and replaces the contents of this block. */
435 template <typename Src1SampleType, typename Src2SampleType>
436 AudioBlock& replaceWithDifferenceOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { replaceWithDifferenceOfInternal (src1, src2); return *this; }
437 template <typename Src1SampleType, typename Src2SampleType>
438 const AudioBlock& replaceWithDifferenceOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { replaceWithDifferenceOfInternal (src1, src2); return *this; }
440 //==============================================================================
441 /** Multiplies the elements in this block by a fixed value. */
442 AudioBlock& JUCE_VECTOR_CALLTYPE multiplyBy (NumericType value) noexcept { multiplyByInternal (value); return *this; }
443 const AudioBlock& JUCE_VECTOR_CALLTYPE multiplyBy (NumericType value) const noexcept { multiplyByInternal (value); return *this; }
445 /** Multiplies the elements in this block by the elements in the src block */
446 template <typename OtherSampleType>
447 AudioBlock& multiplyBy (AudioBlock<OtherSampleType> src) noexcept { multiplyByInternal (src); return *this; }
448 template <typename OtherSampleType>
449 const AudioBlock& multiplyBy (AudioBlock<OtherSampleType> src) const noexcept { multiplyByInternal (src); return *this; }
451 /** Replaces the elements in this block with the product of the elements in the source src block and a fixed value. */
452 template <typename OtherSampleType>
453 AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, NumericType value) noexcept { replaceWithProductOfInternal (src, value); return *this; }
454 template <typename OtherSampleType>
455 const AudioBlock& JUCE_VECTOR_CALLTYPE replaceWithProductOf (AudioBlock<OtherSampleType> src, NumericType value) const noexcept { replaceWithProductOfInternal (src, value); return *this; }
457 /** Replaces the elements in this block with the product of the elements in the src1 and scr2 blocks. */
458 template <typename Src1SampleType, typename Src2SampleType>
459 AudioBlock& replaceWithProductOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { replaceWithProductOfInternal (src1, src2); return *this; }
460 template <typename Src1SampleType, typename Src2SampleType>
461 const AudioBlock& replaceWithProductOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { replaceWithProductOfInternal (src1, src2); return *this; }
463 //==============================================================================
464 /** Multiplies each channels of this block by a smoothly changing value. */
465 template <typename OtherSampleType, typename SmoothingType>
466 AudioBlock& multiplyBy (SmoothedValue<OtherSampleType, SmoothingType>& value) noexcept { multiplyByInternal (value); return *this; }
467 template <typename OtherSampleType, typename SmoothingType>
468 const AudioBlock& multiplyBy (SmoothedValue<OtherSampleType, SmoothingType>& value) const noexcept { multiplyByInternal (value); return *this; }
470 /** Replaces each channel of this block with the product of the src block and a smoothed value. */
471 template <typename BlockSampleType, typename SmootherSampleType, typename SmoothingType>
472 AudioBlock& replaceWithProductOf (AudioBlock<BlockSampleType> src, SmoothedValue<SmootherSampleType, SmoothingType>& value) noexcept { replaceWithProductOfInternal (src, value); return *this; }
473 template <typename BlockSampleType, typename SmootherSampleType, typename SmoothingType>
474 const AudioBlock& replaceWithProductOf (AudioBlock<BlockSampleType> src, SmoothedValue<SmootherSampleType, SmoothingType>& value) const noexcept { replaceWithProductOfInternal (src, value); return *this; }
476 //==============================================================================
477 /** Multiplies each value in src by a fixed value and adds the result to this block. */
478 template <typename OtherSampleType>
479 AudioBlock& JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, NumericType factor) noexcept { addProductOfInternal (src, factor); return *this; }
480 template <typename OtherSampleType>
481 const AudioBlock& JUCE_VECTOR_CALLTYPE addProductOf (AudioBlock<OtherSampleType> src, NumericType factor) const noexcept { addProductOfInternal (src, factor); return *this; }
483 /** Multiplies each value in srcA with the corresponding value in srcB and adds the result to this block. */
484 template <typename Src1SampleType, typename Src2SampleType>
485 AudioBlock& addProductOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { addProductOfInternal (src1, src2); return *this; }
486 template <typename Src1SampleType, typename Src2SampleType>
487 const AudioBlock& addProductOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { addProductOfInternal (src1, src2); return *this; }
489 //==============================================================================
490 /** Negates each value of this block. */
491 AudioBlock& negate() noexcept { negateInternal(); return *this; }
492 const AudioBlock& negate() const noexcept { negateInternal(); return *this; }
494 /** Replaces the contents of this block with the negative of the values in the src block. */
495 template <typename OtherSampleType>
496 AudioBlock& replaceWithNegativeOf (AudioBlock<OtherSampleType> src) noexcept { replaceWithNegativeOfInternal (src); return *this; }
497 template <typename OtherSampleType>
498 const AudioBlock& replaceWithNegativeOf (AudioBlock<OtherSampleType> src) const noexcept { replaceWithNegativeOfInternal (src); return *this; }
500 /** Replaces the contents of this block with the absolute values of the src block. */
501 template <typename OtherSampleType>
502 AudioBlock& replaceWithAbsoluteValueOf (AudioBlock<OtherSampleType> src) noexcept { replaceWithAbsoluteValueOfInternal (src); return *this; }
503 template <typename OtherSampleType>
504 const AudioBlock& replaceWithAbsoluteValueOf (AudioBlock<OtherSampleType> src) const noexcept { replaceWithAbsoluteValueOfInternal (src); return *this; }
506 //==============================================================================
507 /** Replaces each element of this block with the minimum of the corresponding element of the source arrays. */
508 template <typename Src1SampleType, typename Src2SampleType>
509 AudioBlock& replaceWithMinOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { replaceWithMinOfInternal (src1, src2); return *this; }
510 template <typename Src1SampleType, typename Src2SampleType>
511 const AudioBlock& replaceWithMinOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { replaceWithMinOfInternal (src1, src2); return *this; }
513 /** Replaces each element of this block with the maximum of the corresponding element of the source arrays. */
514 template <typename Src1SampleType, typename Src2SampleType>
515 AudioBlock& replaceWithMaxOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept { replaceWithMaxOfInternal (src1, src2); return *this; }
516 template <typename Src1SampleType, typename Src2SampleType>
517 const AudioBlock& replaceWithMaxOf (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept { replaceWithMaxOfInternal (src1, src2); return *this; }
519 //==============================================================================
520 /** Finds the minimum and maximum value of the buffer. */
521 Range<typename std::remove_const<NumericType>::type> findMinAndMax() const noexcept
523 if (numChannels == 0)
524 return {};
526 auto n = numSamples * sizeFactor;
527 auto minmax = FloatVectorOperations::findMinAndMax (getDataPointer (0), n);
529 for (size_t ch = 1; ch < numChannels; ++ch)
530 minmax = minmax.getUnionWith (FloatVectorOperations::findMinAndMax (getDataPointer (ch), n));
532 return minmax;
535 //==============================================================================
536 // Convenient operator wrappers.
537 AudioBlock& JUCE_VECTOR_CALLTYPE operator+= (NumericType value) noexcept { return add (value); }
538 const AudioBlock& JUCE_VECTOR_CALLTYPE operator+= (NumericType value) const noexcept { return add (value); }
540 AudioBlock& operator+= (AudioBlock src) noexcept { return add (src); }
541 const AudioBlock& operator+= (AudioBlock src) const noexcept { return add (src); }
543 AudioBlock& JUCE_VECTOR_CALLTYPE operator-= (NumericType value) noexcept { return subtract (value); }
544 const AudioBlock& JUCE_VECTOR_CALLTYPE operator-= (NumericType value) const noexcept { return subtract (value); }
546 AudioBlock& operator-= (AudioBlock src) noexcept { return subtract (src); }
547 const AudioBlock& operator-= (AudioBlock src) const noexcept { return subtract (src); }
549 AudioBlock& JUCE_VECTOR_CALLTYPE operator*= (NumericType value) noexcept { return multiplyBy (value); }
550 const AudioBlock& JUCE_VECTOR_CALLTYPE operator*= (NumericType value) const noexcept { return multiplyBy (value); }
552 AudioBlock& operator*= (AudioBlock src) noexcept { return multiplyBy (src); }
553 const AudioBlock& operator*= (AudioBlock src) const noexcept { return multiplyBy (src); }
555 template <typename OtherSampleType, typename SmoothingType>
556 AudioBlock& operator*= (SmoothedValue<OtherSampleType, SmoothingType>& value) noexcept { return multiplyBy (value); }
557 template <typename OtherSampleType, typename SmoothingType>
558 const AudioBlock& operator*= (SmoothedValue<OtherSampleType, SmoothingType>& value) const noexcept { return multiplyBy (value); }
560 //==============================================================================
561 // This class can only be used with floating point types
562 static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value
563 || std::is_same<std::remove_const_t<SampleType>, double>::value
564 #if JUCE_USE_SIMD
565 || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value
566 || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value
567 #endif
568 , "AudioBlock only supports single or double precision floating point types");
570 //==============================================================================
571 /** Applies a function to each value in an input block, putting the result into an output block.
572 The function supplied must take a SampleType as its parameter, and return a SampleType.
573 The two blocks must have the same number of channels and samples.
575 template <typename Src1SampleType, typename Src2SampleType, typename FunctionType>
576 static void process (AudioBlock<Src1SampleType> inBlock, AudioBlock<Src2SampleType> outBlock, FunctionType&& function)
578 auto len = inBlock.getNumSamples();
579 auto numChans = inBlock.getNumChannels();
581 jassert (len == outBlock.getNumSamples());
582 jassert (numChans == outBlock.getNumChannels());
584 for (ChannelCountType c = 0; c < numChans; ++c)
586 auto* src = inBlock.getChannelPointer (c);
587 auto* dst = outBlock.getChannelPointer (c);
589 for (size_t i = 0; i < len; ++i)
590 dst[i] = function (src[i]);
594 private:
595 NumericType* getDataPointer (size_t channel) const noexcept
597 return reinterpret_cast<NumericType*> (getChannelPointer (channel));
600 //==============================================================================
601 void JUCE_VECTOR_CALLTYPE clearInternal() const noexcept
603 auto n = numSamples * sizeFactor;
605 for (size_t ch = 0; ch < numChannels; ++ch)
606 FloatVectorOperations::clear (getDataPointer (ch), n);
609 void JUCE_VECTOR_CALLTYPE fillInternal (NumericType value) const noexcept
611 auto n = numSamples * sizeFactor;
613 for (size_t ch = 0; ch < numChannels; ++ch)
614 FloatVectorOperations::fill (getDataPointer (ch), value, n);
617 template <typename OtherSampleType>
618 void copyFromInternal (const AudioBlock<OtherSampleType>& src) const noexcept
620 auto maxChannels = jmin (src.numChannels, numChannels);
621 auto n = jmin (src.numSamples * src.sizeFactor, numSamples * sizeFactor);
623 for (size_t ch = 0; ch < maxChannels; ++ch)
624 FloatVectorOperations::copy (getDataPointer (ch), src.getDataPointer (ch), n);
627 template <typename OtherNumericType>
628 void copyFromInternal (const AudioBuffer<OtherNumericType>& src, size_t srcPos, size_t dstPos, size_t numElements) const
630 auto srclen = static_cast<size_t> (src.getNumSamples()) / sizeFactor;
631 auto n = jmin (srclen - srcPos, numSamples - dstPos, numElements) * sizeFactor;
632 auto maxChannels = jmin (static_cast<size_t> (src.getNumChannels()), static_cast<size_t> (numChannels));
634 for (size_t ch = 0; ch < maxChannels; ++ch)
635 FloatVectorOperations::copy (getDataPointer (ch) + (dstPos * sizeFactor),
636 src.getReadPointer ((int) ch, (int) (srcPos * sizeFactor)),
640 void moveInternal (size_t srcPos, size_t dstPos,
641 size_t numElements = std::numeric_limits<size_t>::max()) const noexcept
643 jassert (srcPos <= numSamples && dstPos <= numSamples);
644 auto len = jmin (numSamples - srcPos, numSamples - dstPos, numElements) * sizeof (SampleType);
646 if (len != 0)
647 for (size_t ch = 0; ch < numChannels; ++ch)
648 ::memmove (getChannelPointer (ch) + dstPos,
649 getChannelPointer (ch) + srcPos, len);
652 //==============================================================================
653 void JUCE_VECTOR_CALLTYPE addInternal (NumericType value) const noexcept
655 auto n = numSamples * sizeFactor;
657 for (size_t ch = 0; ch < numChannels; ++ch)
658 FloatVectorOperations::add (getDataPointer (ch), value, n);
661 template <typename OtherSampleType>
662 void addInternal (AudioBlock<OtherSampleType> src) const noexcept
664 jassert (numChannels == src.numChannels);
665 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
667 for (size_t ch = 0; ch < numChannels; ++ch)
668 FloatVectorOperations::add (getDataPointer (ch), src.getDataPointer (ch), n);
671 template <typename OtherSampleType>
672 void JUCE_VECTOR_CALLTYPE replaceWithSumOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept
674 jassert (numChannels == src.numChannels);
675 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
677 for (size_t ch = 0; ch < numChannels; ++ch)
678 FloatVectorOperations::add (getDataPointer (ch), src.getDataPointer (ch), value, n);
681 template <typename Src1SampleType, typename Src2SampleType>
682 void replaceWithSumOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
684 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
685 auto n = jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor;
687 for (size_t ch = 0; ch < numChannels; ++ch)
688 FloatVectorOperations::add (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
691 //==============================================================================
692 constexpr void JUCE_VECTOR_CALLTYPE subtractInternal (NumericType value) const noexcept
694 addInternal (value * static_cast<NumericType> (-1.0));
697 template <typename OtherSampleType>
698 void subtractInternal (AudioBlock<OtherSampleType> src) const noexcept
700 jassert (numChannels == src.numChannels);
701 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
703 for (size_t ch = 0; ch < numChannels; ++ch)
704 FloatVectorOperations::subtract (getDataPointer (ch), src.getDataPointer (ch), n);
707 template <typename OtherSampleType>
708 void JUCE_VECTOR_CALLTYPE replaceWithDifferenceOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept
710 replaceWithSumOfInternal (src, static_cast<NumericType> (-1.0) * value);
713 template <typename Src1SampleType, typename Src2SampleType>
714 void replaceWithDifferenceOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
716 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
717 auto n = jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor;
719 for (size_t ch = 0; ch < numChannels; ++ch)
720 FloatVectorOperations::subtract (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
723 //==============================================================================
724 void JUCE_VECTOR_CALLTYPE multiplyByInternal (NumericType value) const noexcept
726 auto n = numSamples * sizeFactor;
728 for (size_t ch = 0; ch < numChannels; ++ch)
729 FloatVectorOperations::multiply (getDataPointer (ch), value, n);
732 template <typename OtherSampleType>
733 void multiplyByInternal (AudioBlock<OtherSampleType> src) const noexcept
735 jassert (numChannels == src.numChannels);
736 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
738 for (size_t ch = 0; ch < numChannels; ++ch)
739 FloatVectorOperations::multiply (getDataPointer (ch), src.getDataPointer (ch), n);
742 template <typename OtherSampleType>
743 void JUCE_VECTOR_CALLTYPE replaceWithProductOfInternal (AudioBlock<OtherSampleType> src, NumericType value) const noexcept
745 jassert (numChannels == src.numChannels);
746 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
748 for (size_t ch = 0; ch < numChannels; ++ch)
749 FloatVectorOperations::multiply (getDataPointer (ch), src.getDataPointer (ch), value, n);
752 template <typename Src1SampleType, typename Src2SampleType>
753 void replaceWithProductOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
755 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
756 auto n = jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor;
758 for (size_t ch = 0; ch < numChannels; ++ch)
759 FloatVectorOperations::multiply (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
762 template <typename OtherSampleType, typename SmoothingType>
763 void multiplyByInternal (SmoothedValue<OtherSampleType, SmoothingType>& value) const noexcept
765 if (! value.isSmoothing())
767 multiplyByInternal ((NumericType) value.getTargetValue());
769 else
771 for (size_t i = 0; i < numSamples; ++i)
773 const auto scaler = (NumericType) value.getNextValue();
775 for (size_t ch = 0; ch < numChannels; ++ch)
776 getDataPointer (ch)[i] *= scaler;
781 template <typename BlockSampleType, typename SmootherSampleType, typename SmoothingType>
782 void replaceWithProductOfInternal (AudioBlock<BlockSampleType> src, SmoothedValue<SmootherSampleType, SmoothingType>& value) const noexcept
784 jassert (numChannels == src.numChannels);
786 if (! value.isSmoothing())
788 replaceWithProductOfInternal (src, (NumericType) value.getTargetValue());
790 else
792 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
794 for (size_t i = 0; i < n; ++i)
796 const auto scaler = (NumericType) value.getNextValue();
798 for (size_t ch = 0; ch < numChannels; ++ch)
799 getDataPointer (ch)[i] = scaler * src.getChannelPointer (ch)[i];
804 //==============================================================================
805 template <typename OtherSampleType>
806 void JUCE_VECTOR_CALLTYPE addProductOfInternal (AudioBlock<OtherSampleType> src, NumericType factor) const noexcept
808 jassert (numChannels == src.numChannels);
809 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
811 for (size_t ch = 0; ch < numChannels; ++ch)
812 FloatVectorOperations::addWithMultiply (getDataPointer (ch), src.getDataPointer (ch), factor, n);
815 template <typename Src1SampleType, typename Src2SampleType>
816 void addProductOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
818 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
819 auto n = jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor;
821 for (size_t ch = 0; ch < numChannels; ++ch)
822 FloatVectorOperations::addWithMultiply (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
825 //==============================================================================
826 constexpr void negateInternal() const noexcept
828 multiplyByInternal (static_cast<NumericType> (-1.0));
831 template <typename OtherSampleType>
832 void replaceWithNegativeOfInternal (AudioBlock<OtherSampleType> src) const noexcept
834 jassert (numChannels == src.numChannels);
835 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
837 for (size_t ch = 0; ch < numChannels; ++ch)
838 FloatVectorOperations::negate (getDataPointer (ch), src.getDataPointer (ch), n);
841 template <typename OtherSampleType>
842 void replaceWithAbsoluteValueOfInternal (AudioBlock<OtherSampleType> src) const noexcept
844 jassert (numChannels == src.numChannels);
845 auto n = jmin (numSamples, src.numSamples) * sizeFactor;
847 for (size_t ch = 0; ch < numChannels; ++ch)
848 FloatVectorOperations::abs (getDataPointer (ch), src.getDataPointer (ch), n);
851 //==============================================================================
852 template <typename Src1SampleType, typename Src2SampleType>
853 void replaceWithMinOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
855 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
856 auto n = jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor;
858 for (size_t ch = 0; ch < numChannels; ++ch)
859 FloatVectorOperations::min (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
862 template <typename Src1SampleType, typename Src2SampleType>
863 void replaceWithMaxOfInternal (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) const noexcept
865 jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
866 auto n = jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor;
868 for (size_t ch = 0; ch < numChannels; ++ch)
869 FloatVectorOperations::max (getDataPointer (ch), src1.getDataPointer (ch), src2.getDataPointer (ch), n);
872 //==============================================================================
873 using ChannelCountType = unsigned int;
875 //==============================================================================
876 static constexpr size_t sizeFactor = sizeof (SampleType) / sizeof (NumericType);
877 static constexpr size_t elementMask = sizeFactor - 1;
878 static constexpr size_t byteMask = (sizeFactor * sizeof (NumericType)) - 1;
880 #if JUCE_USE_SIMD
881 static constexpr size_t defaultAlignment = sizeof (SIMDRegister<NumericType>);
882 #else
883 static constexpr size_t defaultAlignment = sizeof (NumericType);
884 #endif
886 SampleType* const* channels;
887 ChannelCountType numChannels = 0;
888 size_t startSample = 0, numSamples = 0;
890 template <typename OtherSampleType>
891 friend class AudioBlock;
894 } // namespace dsp
895 } // namespace juce