32 template <
typename SampleType>
37 using NumericType =
typename SampleTypeHelpers::ElementType<SampleType>::Type;
40 :
UnitTest (
"AudioBlock", UnitTestCategories::dsp)
42 for (
auto v : { &data, &otherData })
43 for (
auto& channel : *v)
44 channel = allocateAlignedMemory (numSamples);
46 block = { data.data(), data.size(), (size_t) numSamples };
47 otherBlock = { otherData.data(), otherData.size(), (size_t) numSamples };
54 for (
auto v : { &data, &otherData })
55 for (
auto channel : *v)
56 deallocateAlignedMemory (channel);
64 expect (block != otherBlock);
82 expect (block != otherBlock);
83 expect (block.getSample (0, 0) == SampleType (1.0));
84 expect (block.getSample (0, 4) == SampleType (5.0));
85 expect (otherBlock.getSample (0, 0) == SampleType (-1.0));
86 expect (otherBlock.getSample (0, 3) == SampleType (-4.0));
88 block.swap (otherBlock);
90 expect (block != otherBlock);
91 expect (otherBlock.getSample (0, 0) == SampleType (1.0));
92 expect (otherBlock.getSample (0, 4) == SampleType (5.0));
93 expect (block.getSample (0, 0) == SampleType (-1.0));
94 expect (block.getSample (0, 3) == SampleType (-4.0));
96 block.swap (otherBlock);
98 expect (block.getSample (0, 0) == SampleType (1.0));
99 expect (block.getSample (0, 4) == SampleType (5.0));
100 expect (otherBlock.getSample (0, 0) == SampleType (-1.0));
101 expect (otherBlock.getSample (0, 3) == SampleType (-4.0));
108 expectEquals ((
int) block.getNumChannels(), (int) data.size());
111 expect (block.getChannelPointer (0)[2] == SampleType (3.0));
112 block.getChannelPointer (0)[2] = SampleType (999.0);
113 expect (block.getChannelPointer (0)[2] == SampleType (999.0));
115 expect (block.getSample (0, 4) == SampleType (5.0));
116 expect (block.getSample (1, 4) == SampleType (11.0));
118 expect (block.getSingleChannelBlock (1).getSample (0, 3) == block.getSample (1, 3));
120 expect (block.getSubsetChannelBlock (0, 2).getSample (1, 3) == block.getSample (1, 3));
121 expect (block.getSubsetChannelBlock (1, 1).getSample (0, 3) == block.getSample (1, 3));
123 block.setSample (1, 1, SampleType (777.0));
124 expect (block.getSample (1, 1) == SampleType (777.0));
126 block.addSample (1, 1, SampleType (1.0));
127 expect (block.getSample (1, 1) == SampleType (778.0));
133 expect (block.getSample (0, 2) == SampleType (0.0));
134 expect (block.getSample (1, 4) == SampleType (0.0));
136 block.fill ((NumericType) 456.0);
137 expect (block.getSample (0, 2) == SampleType (456.0));
138 expect (block.getSample (1, 4) == SampleType (456.0));
140 block.copyFrom (otherBlock);
141 expect (block != otherBlock);
142 expect (block.getSample (0, 2) == otherBlock.getSample (0, 2));
143 expect (block.getSample (1, 4) == otherBlock.getSample (1, 4));
147 SampleType testSample1 = block.getSample (0, 2);
148 SampleType testSample2 = block.getSample (1, 3);
149 expect (testSample1 != block.getSample (0, 4));
150 expect (testSample2 != block.getSample (1, 5));
152 expect (block.getSample (0, 4) == testSample1);
153 expect (block.getSample (1, 5) == testSample2);
160 block.add ((NumericType) 15.0);
161 expect (block.getSample (0, 4) == SampleType (20.0));
162 expect (block.getSample (1, 4) == SampleType (26.0));
164 block.add (otherBlock);
165 expect (block.getSample (0, 4) == SampleType (15.0));
166 expect (block.getSample (1, 4) == SampleType (15.0));
168 block.replaceWithSumOf (otherBlock, (NumericType) 9.0);
169 expect (block.getSample (0, 4) == SampleType (4.0));
170 expect (block.getSample (1, 4) == SampleType (-2.0));
174 block.replaceWithSumOf (block, otherBlock);
175 expect (block.getSample (0, 4) == SampleType (0.0));
176 expect (block.getSample (1, 4) == SampleType (0.0));
183 block.subtract ((NumericType) 15.0);
184 expect (block.getSample (0, 4) == SampleType (-10.0));
185 expect (block.getSample (1, 4) == SampleType (-4.0));
187 block.subtract (otherBlock);
188 expect (block.getSample (0, 4) == SampleType (-5.0));
189 expect (block.getSample (1, 4) == SampleType (7.0));
191 block.replaceWithDifferenceOf (otherBlock, (NumericType) 9.0);
192 expect (block.getSample (0, 4) == SampleType (-14.0));
193 expect (block.getSample (1, 4) == SampleType (-20.0));
197 block.replaceWithDifferenceOf (block, otherBlock);
198 expect (block.getSample (0, 4) == SampleType (10.0));
199 expect (block.getSample (1, 4) == SampleType (22.0));
206 block.multiplyBy ((NumericType) 10.0);
207 expect (block.getSample (0, 4) == SampleType (50.0));
208 expect (block.getSample (1, 4) == SampleType (110.0));
210 block.multiplyBy (otherBlock);
211 expect (block.getSample (0, 4) == SampleType (-250.0));
212 expect (block.getSample (1, 4) == SampleType (-1210.0));
214 block.replaceWithProductOf (otherBlock, (NumericType) 3.0);
215 expect (block.getSample (0, 4) == SampleType (-15.0));
216 expect (block.getSample (1, 4) == SampleType (-33.0));
220 block.replaceWithProductOf (block, otherBlock);
221 expect (block.getSample (0, 4) == SampleType (-25.0));
222 expect (block.getSample (1, 4) == SampleType (-121.0));
229 block.addProductOf (otherBlock, (NumericType) -1.0);
230 expect (block.getSample (0, 4) == SampleType (10.0));
231 expect (block.getSample (1, 4) == SampleType (22.0));
233 block.addProductOf (otherBlock, otherBlock);
234 expect (block.getSample (0, 4) == SampleType (35.0));
235 expect (block.getSample (1, 4) == SampleType (143.0));
243 block.add (otherBlock);
244 expect (block.getSample (0, 4) == SampleType (10.0));
245 expect (block.getSample (1, 4) == SampleType (22.0));
247 block.replaceWithNegativeOf (otherBlock);
248 expect (block.getSample (0, 4) == SampleType (-5.0));
249 expect (block.getSample (1, 4) == SampleType (-11.0));
253 block.replaceWithAbsoluteValueOf (otherBlock);
254 expect (block.getSample (0, 4) == SampleType (5.0));
255 expect (block.getSample (1, 4) == SampleType (11.0));
258 block.replaceWithMinOf (block, otherBlock);
259 expect (block.getSample (0, 4) == SampleType (-5.0));
260 expect (block.getSample (1, 4) == SampleType (-11.0));
263 block.replaceWithMaxOf (block, otherBlock);
264 expect (block.getSample (0, 4) == SampleType (5.0));
265 expect (block.getSample (1, 4) == SampleType (11.0));
268 auto range = block.findMinAndMax();
269 expect (SampleType (range.getStart()) == SampleType (1.0));
270 expect (SampleType (range.getEnd()) == SampleType (12.0));
276 block += (NumericType) 10.0;
277 expect (block.getSample (0, 4) == SampleType (15.0));
278 expect (block.getSample (1, 4) == SampleType (21.0));
280 expect (block.getSample (0, 4) == SampleType (10.0));
281 expect (block.getSample (1, 4) == SampleType (10.0));
284 block -= (NumericType) 10.0;
285 expect (block.getSample (0, 4) == SampleType (-5.0));
286 expect (block.getSample (1, 4) == SampleType (1.0));
288 expect (block.getSample (0, 4) == SampleType (0.0));
289 expect (block.getSample (1, 4) == SampleType (12.0));
292 block *= (NumericType) 10.0;
293 expect (block.getSample (0, 4) == SampleType (50.0));
294 expect (block.getSample (1, 4) == SampleType (110.0));
296 expect (block.getSample (0, 4) == SampleType (-250.0));
297 expect (block.getSample (1, 4) == SampleType (-1210.0));
304 expect (otherBlock.getSample (0, 4) == SampleType (6.0));
305 expect (otherBlock.getSample (1, 4) == SampleType (12.0));
317 smoothedValueTests();
323 template <
typename T>
324 using ScalarVoid =
typename std::enable_if_t < std::is_scalar <T>::value,
void>;
326 template <
typename T>
327 using SIMDVoid =
typename std::enable_if_t <! std::is_scalar <T>::value,
void>;
330 template <
typename T = SampleType>
331 ScalarVoid<T> copyingTests()
333 auto unchangedElement1 = block.getSample (0, 4);
334 auto unchangedElement2 = block.getSample (1, 1);
338 block.copyFrom (otherBuffer, 1, 2, 2);
340 expectEquals (block.getSample (0, 4), unchangedElement1);
341 expectEquals (block.getSample (1, 1), unchangedElement2);
342 expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));
343 expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));
347 unchangedElement1 = otherBuffer.getSample (0, 4);
348 unchangedElement2 = otherBuffer.getSample (1, 3);
350 block.copyTo (otherBuffer, 2, 1, 2);
352 expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);
353 expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);
354 expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));
355 expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));
358 template <
typename T = SampleType>
359 SIMDVoid<T> copyingTests()
363 (int) (block.getNumSamples() * numSIMDElements));
370 auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);
371 auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);
372 auto unchangedElement1 = numericData.
getSample (0, lastUnchangedIndexBeforeCopiedRange);
373 auto unchangedElement2 = numericData.
getSample (1, firstUnchangedIndexAfterCopiedRange);
375 block.copyTo (numericData, 1, 2, 2);
379 expect (SampleType (numericData.
getSample (0, 2 * (
int) numSIMDElements)) == block.getSample (0, 1));
380 expect (SampleType (numericData.
getSample (1, 3 * (
int) numSIMDElements)) == block.getSample (1, 2));
384 auto unchangedSIMDElement1 = block.getSample (0, 1);
385 auto unchangedSIMDElement2 = block.getSample (1, 4);
387 block.copyFrom (numericData, 1, 2, 2);
389 expect (block.getSample (0, 1) == unchangedSIMDElement1);
390 expect (block.getSample (1, 4) == unchangedSIMDElement2);
392 expectEquals (block.getSample (1, 3).get (0), numericData.
getSample (1, (
int) (numSIMDElements * 2)));
394 if (numSIMDElements > 1)
396 expectEquals (block.getSample (0, 2).get (1), numericData.
getSample (0, (
int) (numSIMDElements + 1)));
397 expectEquals (block.getSample (1, 3).get (1), numericData.
getSample (1, (
int) ((numSIMDElements * 2) + 1)));
402 template <
typename T = SampleType>
403 ScalarVoid<T> smoothedValueTests()
405 block.fill ((SampleType) 1.0);
408 sv.setTargetValue ((SampleType) 0.0);
410 block.multiplyBy (sv);
411 expect (block.getSample (0, 2) < (SampleType) 1.0);
412 expect (block.getSample (1, 2) < (SampleType) 1.0);
413 expect (block.getSample (0, 2) > (SampleType) 0.0);
414 expect (block.getSample (1, 2) > (SampleType) 0.0);
415 expectEquals (block.getSample (0, 5), (SampleType) 0.0);
416 expectEquals (block.getSample (1, 5), (SampleType) 0.0);
418 sv.setCurrentAndTargetValue (-1.0f);
419 sv.setTargetValue (0.0f);
420 otherBlock.fill (-1.0f);
421 block.replaceWithProductOf (otherBlock, sv);
422 expect (block.getSample (0, 2) < (SampleType) 1.0);
423 expect (block.getSample (1, 2) < (SampleType) 1.0);
424 expect (block.getSample (0, 2) > (SampleType) 0.0);
425 expect (block.getSample (1, 2) > (SampleType) 0.0);
426 expectEquals (block.getSample (0, 5), (SampleType) 0.0);
427 expectEquals (block.getSample (1, 5), (SampleType) 0.0);
430 template <
typename T = SampleType>
431 SIMDVoid<T> smoothedValueTests() {}
436 auto value = SampleType (1.0);
438 for (
size_t c = 0; c < block.getNumChannels(); ++c)
440 for (
size_t i = 0; i < block.getNumSamples(); ++i)
442 block.setSample ((
int) c, (
int) i, value);
443 value += SampleType (1.0);
447 otherBlock.replaceWithNegativeOf (block);
451 static SampleType* allocateAlignedMemory (
int numSamplesToAllocate)
453 auto alignmentLowerBound = std::alignment_of<SampleType>::value;
455 alignmentLowerBound = jmax (
sizeof (
void*), alignmentLowerBound);
457 auto alignmentOrder = std::ceil (std::log2 (alignmentLowerBound));
458 auto requiredAlignment = (size_t) std::pow (2, alignmentOrder);
460 auto size = (size_t) numSamplesToAllocate *
sizeof (SampleType);
463 auto* memory = _aligned_malloc (size, requiredAlignment);
466 auto result = posix_memalign (&memory, requiredAlignment, size);
475 return static_cast<SampleType*
> (memory);
478 void deallocateAlignedMemory (
void* address)
481 _aligned_free (address);
488 static constexpr
int numChannels = 2, numSamples = 6;
489 std::array<SampleType*, numChannels> data, otherData;
A utility class for values that need smoothing to avoid audio glitches.
UnitTest(const String &name, const String &category=String())
Creates a test with the given name and optionally places it in a category.
Minimal and lightweight data-structure which contains a list of pointers to channels containing some ...
void reset(double sampleRate, double rampLengthInSeconds) noexcept
Reset to a new sample rate and ramp length.
Type getSample(int channel, int sampleIndex) const noexcept
Returns a sample from the buffer.
A wrapper around the platform's native SIMD register type.
void expectEquals(ValueType actual, ValueType expected, String failureMessage=String())
Compares a value to an expected value.
static void process(AudioBlock< Src1SampleType > inBlock, AudioBlock< Src2SampleType > outBlock, FunctionType &&function)
Applies a function to each value in an input block, putting the result into an output block...
This is a base class for classes that perform a unit test.
void runTest() override
Implement this method in your subclass to actually run your tests.
void beginTest(const String &testName)
Tells the system that a new subsection of tests is beginning.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
void applyGainRamp(int channel, int startSample, int numSamples, Type startGain, Type endGain) noexcept
Applies a range of gains to a region of a channel.
void expect(bool testResult, const String &failureMessage=String())
Checks that the result of a test is true, and logs this result.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.