OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_AudioBlock_test.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29namespace dsp
30{
31
32template <typename SampleType>
33class AudioBlockUnitTests : public UnitTest
34{
35public:
36 //==============================================================================
37 using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
38
39 AudioBlockUnitTests()
40 : UnitTest ("AudioBlock", UnitTestCategories::dsp)
41 {
42 for (auto v : { &data, &otherData })
43 for (auto& channel : *v)
44 channel = allocateAlignedMemory (numSamples);
45
46 block = { data.data(), data.size(), (size_t) numSamples };
47 otherBlock = { otherData.data(), otherData.size(), (size_t) numSamples };
48
49 resetBlocks();
50 }
51
52 ~AudioBlockUnitTests() override
53 {
54 for (auto v : { &data, &otherData })
55 for (auto channel : *v)
56 deallocateAlignedMemory (channel);
57 }
58
59 void runTest() override
60 {
61 beginTest ("Equality");
62 {
63 expect (block == block);
64 expect (block != otherBlock);
65 }
66
67 beginTest ("Constructors");
68 {
69 expect (block == AudioBlock<SampleType> (data.data(), data.size(), numSamples));
70 expect (block == AudioBlock<SampleType> (data.data(), data.size(), (size_t) 0, numSamples));
71 expect (block == AudioBlock<SampleType> (block));
72
73 expect (block == AudioBlock<const SampleType> (data.data(), data.size(), numSamples));
74 expect (block == AudioBlock<const SampleType> (data.data(), data.size(), (size_t) 0, numSamples));
75 expect (block == AudioBlock<const SampleType> (block));
76 }
77
78 beginTest ("Swap");
79 {
80 resetBlocks();
81
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));
87
88 block.swap (otherBlock);
89
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));
95
96 block.swap (otherBlock);
97
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));
102 }
103
104 beginTest ("Getters and setters");
105 {
106 resetBlocks();
107
108 expectEquals ((int) block.getNumChannels(), (int) data.size());
109 expectEquals ((int) block.getNumSamples(), numSamples);
110
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));
114
115 expect (block.getSample (0, 4) == SampleType (5.0));
116 expect (block.getSample (1, 4) == SampleType (11.0));
117
118 expect (block.getSingleChannelBlock (1).getSample (0, 3) == block.getSample (1, 3));
119
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));
122
123 block.setSample (1, 1, SampleType (777.0));
124 expect (block.getSample (1, 1) == SampleType (777.0));
125
126 block.addSample (1, 1, SampleType (1.0));
127 expect (block.getSample (1, 1) == SampleType (778.0));
128 }
129
130 beginTest ("Basic copying");
131 {
132 block.clear();
133 expect (block.getSample (0, 2) == SampleType (0.0));
134 expect (block.getSample (1, 4) == SampleType (0.0));
135
136 block.fill ((NumericType) 456.0);
137 expect (block.getSample (0, 2) == SampleType (456.0));
138 expect (block.getSample (1, 4) == SampleType (456.0));
139
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));
144
145 resetBlocks();
146
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));
151 block.move (0, 2);
152 expect (block.getSample (0, 4) == testSample1);
153 expect (block.getSample (1, 5) == testSample2);
154 }
155
156 beginTest ("Addition");
157 {
158 resetBlocks();
159
160 block.add ((NumericType) 15.0);
161 expect (block.getSample (0, 4) == SampleType (20.0));
162 expect (block.getSample (1, 4) == SampleType (26.0));
163
164 block.add (otherBlock);
165 expect (block.getSample (0, 4) == SampleType (15.0));
166 expect (block.getSample (1, 4) == SampleType (15.0));
167
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));
171
172 resetBlocks();
173
174 block.replaceWithSumOf (block, otherBlock);
175 expect (block.getSample (0, 4) == SampleType (0.0));
176 expect (block.getSample (1, 4) == SampleType (0.0));
177 }
178
179 beginTest ("Subtraction");
180 {
181 resetBlocks();
182
183 block.subtract ((NumericType) 15.0);
184 expect (block.getSample (0, 4) == SampleType (-10.0));
185 expect (block.getSample (1, 4) == SampleType (-4.0));
186
187 block.subtract (otherBlock);
188 expect (block.getSample (0, 4) == SampleType (-5.0));
189 expect (block.getSample (1, 4) == SampleType (7.0));
190
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));
194
195 resetBlocks();
196
197 block.replaceWithDifferenceOf (block, otherBlock);
198 expect (block.getSample (0, 4) == SampleType (10.0));
199 expect (block.getSample (1, 4) == SampleType (22.0));
200 }
201
202 beginTest ("Multiplication");
203 {
204 resetBlocks();
205
206 block.multiplyBy ((NumericType) 10.0);
207 expect (block.getSample (0, 4) == SampleType (50.0));
208 expect (block.getSample (1, 4) == SampleType (110.0));
209
210 block.multiplyBy (otherBlock);
211 expect (block.getSample (0, 4) == SampleType (-250.0));
212 expect (block.getSample (1, 4) == SampleType (-1210.0));
213
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));
217
218 resetBlocks();
219
220 block.replaceWithProductOf (block, otherBlock);
221 expect (block.getSample (0, 4) == SampleType (-25.0));
222 expect (block.getSample (1, 4) == SampleType (-121.0));
223 }
224
225 beginTest ("Multiply add");
226 {
227 resetBlocks();
228
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));
232
233 block.addProductOf (otherBlock, otherBlock);
234 expect (block.getSample (0, 4) == SampleType (35.0));
235 expect (block.getSample (1, 4) == SampleType (143.0));
236 }
237
238 beginTest ("Negative abs min max");
239 {
240 resetBlocks();
241 otherBlock.negate();
242
243 block.add (otherBlock);
244 expect (block.getSample (0, 4) == SampleType (10.0));
245 expect (block.getSample (1, 4) == SampleType (22.0));
246
247 block.replaceWithNegativeOf (otherBlock);
248 expect (block.getSample (0, 4) == SampleType (-5.0));
249 expect (block.getSample (1, 4) == SampleType (-11.0));
250
251 block.clear();
252 otherBlock.negate();
253 block.replaceWithAbsoluteValueOf (otherBlock);
254 expect (block.getSample (0, 4) == SampleType (5.0));
255 expect (block.getSample (1, 4) == SampleType (11.0));
256
257 resetBlocks();
258 block.replaceWithMinOf (block, otherBlock);
259 expect (block.getSample (0, 4) == SampleType (-5.0));
260 expect (block.getSample (1, 4) == SampleType (-11.0));
261
262 resetBlocks();
263 block.replaceWithMaxOf (block, otherBlock);
264 expect (block.getSample (0, 4) == SampleType (5.0));
265 expect (block.getSample (1, 4) == SampleType (11.0));
266
267 resetBlocks();
268 auto range = block.findMinAndMax();
269 expect (SampleType (range.getStart()) == SampleType (1.0));
270 expect (SampleType (range.getEnd()) == SampleType (12.0));
271 }
272
273 beginTest ("Operators");
274 {
275 resetBlocks();
276 block += (NumericType) 10.0;
277 expect (block.getSample (0, 4) == SampleType (15.0));
278 expect (block.getSample (1, 4) == SampleType (21.0));
279 block += otherBlock;
280 expect (block.getSample (0, 4) == SampleType (10.0));
281 expect (block.getSample (1, 4) == SampleType (10.0));
282
283 resetBlocks();
284 block -= (NumericType) 10.0;
285 expect (block.getSample (0, 4) == SampleType (-5.0));
286 expect (block.getSample (1, 4) == SampleType (1.0));
287 block -= otherBlock;
288 expect (block.getSample (0, 4) == SampleType (0.0));
289 expect (block.getSample (1, 4) == SampleType (12.0));
290
291 resetBlocks();
292 block *= (NumericType) 10.0;
293 expect (block.getSample (0, 4) == SampleType (50.0));
294 expect (block.getSample (1, 4) == SampleType (110.0));
295 block *= otherBlock;
296 expect (block.getSample (0, 4) == SampleType (-250.0));
297 expect (block.getSample (1, 4) == SampleType (-1210.0));
298 }
299
300 beginTest ("Process");
301 {
302 resetBlocks();
303 AudioBlock<SampleType>::process (block, otherBlock, [](SampleType x) { return x + (NumericType) 1.0; });
304 expect (otherBlock.getSample (0, 4) == SampleType (6.0));
305 expect (otherBlock.getSample (1, 4) == SampleType (12.0));
306 }
307
308 beginTest ("Copying");
309 {
310 resetBlocks();
311 copyingTests();
312 }
313
314 beginTest ("Smoothing");
315 {
316 resetBlocks();
317 smoothedValueTests();
318 }
319 }
320
321private:
322 //==============================================================================
323 template <typename T>
324 using ScalarVoid = typename std::enable_if_t < std::is_scalar <T>::value, void>;
325
326 template <typename T>
327 using SIMDVoid = typename std::enable_if_t <! std::is_scalar <T>::value, void>;
328
329 //==============================================================================
330 template <typename T = SampleType>
331 ScalarVoid<T> copyingTests()
332 {
333 auto unchangedElement1 = block.getSample (0, 4);
334 auto unchangedElement2 = block.getSample (1, 1);
335
336 AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);
337
338 block.copyFrom (otherBuffer, 1, 2, 2);
339
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));
344
345 resetBlocks();
346
347 unchangedElement1 = otherBuffer.getSample (0, 4);
348 unchangedElement2 = otherBuffer.getSample (1, 3);
349
350 block.copyTo (otherBuffer, 2, 1, 2);
351
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));
356 }
357
358 template <typename T = SampleType>
359 SIMDVoid<T> copyingTests()
360 {
361 auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;
362 AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),
363 (int) (block.getNumSamples() * numSIMDElements));
364
365 for (int c = 0; c < numericData.getNumChannels(); ++c)
366 std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);
367
368 numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);
369
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);
374
375 block.copyTo (numericData, 1, 2, 2);
376
377 expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);
378 expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);
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));
381
382 numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);
383
384 auto unchangedSIMDElement1 = block.getSample (0, 1);
385 auto unchangedSIMDElement2 = block.getSample (1, 4);
386
387 block.copyFrom (numericData, 1, 2, 2);
388
389 expect (block.getSample (0, 1) == unchangedSIMDElement1);
390 expect (block.getSample (1, 4) == unchangedSIMDElement2);
391 expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));
392 expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));
393
394 if (numSIMDElements > 1)
395 {
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)));
398 }
399 }
400
401 //==============================================================================
402 template <typename T = SampleType>
403 ScalarVoid<T> smoothedValueTests()
404 {
405 block.fill ((SampleType) 1.0);
406 SmoothedValue<SampleType> sv { (SampleType) 1.0 };
407 sv.reset (1, 4);
408 sv.setTargetValue ((SampleType) 0.0);
409
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);
417
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);
428 }
429
430 template <typename T = SampleType>
431 SIMDVoid<T> smoothedValueTests() {}
432
433 //==============================================================================
434 void resetBlocks()
435 {
436 auto value = SampleType (1.0);
437
438 for (size_t c = 0; c < block.getNumChannels(); ++c)
439 {
440 for (size_t i = 0; i < block.getNumSamples(); ++i)
441 {
442 block.setSample ((int) c, (int) i, value);
443 value += SampleType (1.0);
444 }
445 }
446
447 otherBlock.replaceWithNegativeOf (block);
448 }
449
450 //==============================================================================
451 static SampleType* allocateAlignedMemory (int numSamplesToAllocate)
452 {
453 auto alignmentLowerBound = std::alignment_of<SampleType>::value;
454 #if ! JUCE_WINDOWS
455 alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);
456 #endif
457 auto alignmentOrder = std::ceil (std::log2 (alignmentLowerBound));
458 auto requiredAlignment = (size_t) std::pow (2, alignmentOrder);
459
460 auto size = (size_t) numSamplesToAllocate * sizeof (SampleType);
461
462 #if JUCE_WINDOWS
463 auto* memory = _aligned_malloc (size, requiredAlignment);
464 #else
465 void* memory;
466 auto result = posix_memalign (&memory, requiredAlignment, size);
467
468 if (result != 0)
469 {
470 jassertfalse;
471 return nullptr;
472 }
473 #endif
474
475 return static_cast<SampleType*> (memory);
476 }
477
478 void deallocateAlignedMemory (void* address)
479 {
480 #if JUCE_WINDOWS
481 _aligned_free (address);
482 #else
483 free (address);
484 #endif
485 }
486
487 //==============================================================================
488 static constexpr int numChannels = 2, numSamples = 6;
489 std::array<SampleType*, numChannels> data, otherData;
490 AudioBlock<SampleType> block, otherBlock;
491};
492
493static AudioBlockUnitTests<float> audioBlockFloatUnitTests;
494static AudioBlockUnitTests<double> audioBlockDoubleUnitTests;
495static AudioBlockUnitTests<SIMDRegister<float>> audioBlockSIMDFloatUnitTests;
496static AudioBlockUnitTests<SIMDRegister<double>> audioBlockSIMDDoubleUnitTests;
497
498} // namespace dsp
499} // namespace juce
void expectEquals(ValueType actual, ValueType expected, String failureMessage=String())
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
static void process(AudioBlock< Src1SampleType > inBlock, AudioBlock< Src2SampleType > outBlock, FunctionType &&function)
static constexpr size_t SIMDNumElements