1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <math.h>
18 #include <vector>
19 
20 #include <gtest/gtest.h>
21 
22 #include <audio_utils/primitives.h>
23 #include <audio_utils/format.h>
24 #include <audio_utils/channels.h>
25 
26 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27 
28 static const int32_t lim8pos = 255;
29 static const int32_t lim8neg = 0;
30 static const int32_t lim16pos = (1 << 15) - 1;
31 static const int32_t lim16neg = -(1 << 15);
32 static const int32_t lim24pos = (1 << 23) - 1;
33 static const int32_t lim24neg = -(1 << 23);
34 static const int64_t lim32pos = 0x000000007fffffff;
35 static const int64_t lim32neg = 0xffffffff80000000;
36 
37 // Use memset here since it is generally the fastest method of clearing data,
38 // but could be changed to std::fill or assignment should those prove faster.
39 template <typename T>
zeroFill(T & container)40 static void zeroFill(T &container) {
41     memset(container.data(), 0, container.size() * sizeof(container[0]));
42 }
43 
testClamp8(float f)44 inline void testClamp8(float f)
45 {
46     // f is in native u8 scaling to test rounding
47     uint8_t uval = clamp8_from_float((f - 128) / (1 << 7));
48 
49     // test clamping
50     if (f > lim8pos) {
51         EXPECT_EQ(lim8pos, uval);
52     } else if (f < lim8neg) {
53         EXPECT_EQ(lim8neg, uval);
54     }
55 
56     // if in range, make sure round trip clamp and conversion is correct.
57     if (f < lim8pos - 1. && f > lim8neg + 1.) {
58         uint8_t uval2 = clamp8_from_float(float_from_u8(uval));
59         int diff = abs(uval - uval2);
60         EXPECT_LE(diff, 1);
61     }
62 }
63 
testClamp16(float f)64 inline void testClamp16(float f)
65 {
66     int16_t ival = clamp16_from_float(f / (1 << 15));
67 
68     // test clamping
69     if (f > lim16pos) {
70         EXPECT_EQ(lim16pos, ival);
71     } else if (f < lim16neg) {
72         EXPECT_EQ(lim16neg, ival);
73     }
74 
75     // if in range, make sure round trip clamp and conversion is correct.
76     if (f < lim16pos - 1. && f > lim16neg + 1.) {
77         int ival2 = clamp16_from_float(float_from_i16(ival));
78         int diff = abs(ival - ival2);
79         EXPECT_LE(diff, 1);
80     }
81 }
82 
testClamp24(float f)83 inline void testClamp24(float f)
84 {
85     int32_t ival = clamp24_from_float(f / (1 << 23));
86 
87     // test clamping
88     if (f > lim24pos) {
89         EXPECT_EQ(lim24pos, ival);
90     } else if (f < lim24neg) {
91         EXPECT_EQ(lim24neg, ival);
92     }
93 
94     // if in range, make sure round trip clamp and conversion is correct.
95     if (f < lim24pos - 1. && f > lim24neg + 1.) {
96         int ival2 = clamp24_from_float(float_from_q8_23(ival));
97         int diff = abs(ival - ival2);
98         EXPECT_LE(diff, 1);
99     }
100 }
101 
102 template<typename T>
checkMonotone(const T * ary,size_t size)103 void checkMonotone(const T *ary, size_t size)
104 {
105     for (size_t i = 1; i < size; ++i) {
106         EXPECT_LT(ary[i-1], ary[i]);
107     }
108 }
109 
checkMonotonep24(uint8_t * pary,size_t size)110 void checkMonotonep24(uint8_t * pary, size_t size)
111 {
112     size_t frames = size/3;
113     for (size_t i = 1; i < frames; ++i) {
114         EXPECT_LT(i32_from_p24(pary + 3*(i-1)), i32_from_p24(pary + 3*i));
115     }
116 }
117 
TEST(audio_utils_primitives,clamp_to_int)118 TEST(audio_utils_primitives, clamp_to_int) {
119     static const float testArray[] = {
120             -NAN, -INFINITY,
121             -1.e20, -32768., 63.9,
122             -3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
123             1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
124             32767., 32768., 1.e20,
125             INFINITY, NAN };
126 
127     for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
128         testClamp8(testArray[i]);
129     }
130     for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
131         testClamp16(testArray[i]);
132     }
133     for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
134         testClamp24(testArray[i]);
135     }
136 
137     // used for ULP testing (tweaking the lsb of the float)
138     union {
139         int32_t i;
140         float f;
141     } val;
142     int32_t res;
143 
144     // check clampq4_27_from_float()
145     val.f = 16.;
146     res = clampq4_27_from_float(val.f);
147     EXPECT_EQ(0x7fffffff, res);
148     val.i--;
149     res = clampq4_27_from_float(val.f);
150     EXPECT_LE(res, 0x7fffffff);
151     EXPECT_GE(res, 0x7fff0000);
152     val.f = -16.;
153     res = clampq4_27_from_float(val.f);
154     EXPECT_EQ((int32_t)0x80000000, res); // negative
155     val.i++;
156     res = clampq4_27_from_float(val.f);
157     EXPECT_GE(res, (int32_t)0x80000000); // negative
158     EXPECT_LE(res, (int32_t)0x80008000); // negative
159 
160     // check u4_28_from_float and u4_12_from_float
161     uint32_t ures;
162     uint16_t ures16;
163     val.f = 16.;
164     ures = u4_28_from_float(val.f);
165     EXPECT_EQ(0xffffffff, ures);
166     ures16 = u4_12_from_float(val.f);
167     EXPECT_EQ(0xffff, ures16);
168 
169     val.f = -1.;
170     ures = u4_28_from_float(val.f);
171     EXPECT_EQ((uint32_t)0, ures);
172     ures16 = u4_12_from_float(val.f);
173     EXPECT_EQ(0, ures16);
174 
175     // check float_from_u4_28 and float_from_u4_12 (roundtrip)
176     for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
177         ures = u4_28_from_float(float_from_u4_28(v));
178         EXPECT_EQ(ures, v);
179     }
180     for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
181         ures16 = u4_12_from_float(float_from_u4_12(v));
182         EXPECT_EQ(ures16, v);
183     }
184 
185     // check infinity
186     EXPECT_EQ(0, clamp8_from_float(-INFINITY));
187     EXPECT_EQ(255, clamp8_from_float(INFINITY));
188 }
189 
TEST(audio_utils_primitives,memcpy)190 TEST(audio_utils_primitives, memcpy) {
191     // test round-trip.
192     constexpr size_t size = 65536;
193     std::vector<int16_t> i16ref(size);
194     std::vector<int16_t> i16ary(size);
195     std::vector<int32_t> i32ary(size);
196     std::vector<float> fary(size);
197     std::vector<uint8_t> pary(size * 3);
198 
199 
200     // set signed reference monotonic array from -32768 to 32767
201     for (size_t i = 0; i < i16ref.size(); ++i) {
202         i16ref[i] = i16ary[i] = i - 32768;
203     }
204 
205     // do round-trip testing i16 and float
206     memcpy_to_float_from_i16(fary.data(), i16ary.data(), fary.size());
207     zeroFill(i16ary);
208     checkMonotone(fary.data(), fary.size());
209 
210     memcpy_to_i16_from_float(i16ary.data(), fary.data(), i16ary.size());
211     zeroFill(fary);
212     checkMonotone(i16ary.data(), i16ary.size());
213 
214     // TODO make a template case for the following?
215 
216     // do round-trip testing p24 to i16 and float
217     memcpy_to_p24_from_i16(pary.data(), i16ary.data(), size /* note pary elem is 3 bytes */);
218     zeroFill(i16ary);
219 
220     // check an intermediate format at a position(???)
221 #if 0
222     printf("pary[%d].0 = %u  pary[%d].1 = %u  pary[%d].2 = %u\n",
223             1025, (unsigned) pary[1025*3],
224             1025, (unsigned) pary[1025*3+1],
225             1025, (unsigned) pary[1025*3+2]
226     );
227 #endif
228 
229     memcpy_to_float_from_p24(fary.data(), pary.data(), fary.size());
230     zeroFill(pary);
231     checkMonotone(fary.data(), fary.size());
232 
233     memcpy_to_p24_from_float(pary.data(), fary.data(), size /* note pary elem is 3 bytes */);
234     zeroFill(fary);
235     checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
236 
237     memcpy_to_i16_from_p24(i16ary.data(), pary.data(), i16ary.size());
238     zeroFill(pary);
239     checkMonotone(i16ary.data(), i16ary.size());
240 
241     // do round-trip testing q8_23 to i16 and float
242     memcpy_to_q8_23_from_i16(i32ary.data(), i16ary.data(), i32ary.size());
243     zeroFill(i16ary);
244     checkMonotone(i32ary.data(), i32ary.size());
245 
246     memcpy_to_float_from_q8_23(fary.data(), i32ary.data(), fary.size());
247     zeroFill(i32ary);
248     checkMonotone(fary.data(), fary.size());
249 
250     memcpy_to_q8_23_from_float_with_clamp(i32ary.data(), fary.data(), i32ary.size());
251     zeroFill(fary);
252     checkMonotone(i32ary.data(), i32ary.size());
253 
254     memcpy_to_i16_from_q8_23(i16ary.data(), i32ary.data(), i16ary.size());
255     zeroFill(i32ary);
256     checkMonotone(i16ary.data(), i16ary.size());
257 
258     // do round-trip testing i32 to i16 and float
259     memcpy_to_i32_from_i16(i32ary.data(), i16ary.data(), i32ary.size());
260     zeroFill(i16ary);
261     checkMonotone(i32ary.data(), i32ary.size());
262 
263     memcpy_to_float_from_i32(fary.data(), i32ary.data(), fary.size());
264     zeroFill(i32ary);
265     checkMonotone(fary.data(), fary.size());
266 
267     memcpy_to_i32_from_float(i32ary.data(), fary.data(), i32ary.size());
268     zeroFill(fary);
269     checkMonotone(i32ary.data(), i32ary.size());
270 
271     memcpy_to_i16_from_i32(i16ary.data(), i32ary.data(), i16ary.size());
272     zeroFill(i32ary);
273     checkMonotone(i16ary.data(), i16ary.size());
274 
275     // do round-trip test i16 -> p24 -> i32 -> p24 -> q8_23 -> p24 -> i16
276     memcpy_to_p24_from_i16(pary.data(), i16ary.data(), size /* note pary elem is 3 bytes */);
277     zeroFill(i16ary);
278     checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
279 
280     memcpy_to_i32_from_p24(i32ary.data(), pary.data(), i32ary.size());
281     zeroFill(pary);
282     checkMonotone(i32ary.data(), i32ary.size());
283 
284     memcpy_to_p24_from_i32(pary.data(), i32ary.data(), size /* note pary elem is 3 bytes */);
285     zeroFill(i32ary);
286     checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
287 
288     memcpy_to_q8_23_from_p24(i32ary.data(), pary.data(), i32ary.size());
289     zeroFill(pary);
290     checkMonotone(i32ary.data(), i32ary.size());
291 
292     memcpy_to_p24_from_q8_23(pary.data(), i32ary.data(), size /* note pary elem is 3 bytes */);
293     zeroFill(i32ary);
294     checkMonotonep24(pary.data(), pary.size() /* this is * 3*/);
295 
296     memcpy_to_i16_from_p24(i16ary.data(), pary.data(), i16ary.size());
297     zeroFill(pary);
298     checkMonotone(i16ary.data(), i16ary.size());
299 
300     // do partial round-trip testing q4_27 to i16 and float
301     memcpy_to_float_from_i16(fary.data(), i16ary.data(), fary.size());
302     zeroFill(i16ary);
303 
304     memcpy_to_q4_27_from_float(i32ary.data(), fary.data(), i32ary.size());
305     zeroFill(fary);
306     checkMonotone(i32ary.data(), i32ary.size());
307 
308     memcpy_to_i16_from_q4_27(i16ary.data(), i32ary.data(), i16ary.size());
309     checkMonotone(i16ary.data(), i16ary.size());
310     EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
311 
312     zeroFill(i16ary);
313 
314     // ditherAndClamp() has non-standard parameters - memcpy_to_float_from_q4_27() is preferred
315     ditherAndClamp(reinterpret_cast<int32_t *>(i16ary.data()),
316             i32ary.data(), i16ary.size() / 2);
317     checkMonotone(i16ary.data(), i16ary.size());
318     EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
319 
320     memcpy_to_float_from_q4_27(fary.data(), i32ary.data(), fary.size());
321     zeroFill(i32ary);
322     checkMonotone(fary.data(), fary.size());
323 
324     // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
325     EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), i16ary.size() * sizeof(i16ary[0])));
326 
327     // test round-trip for u8 and float.
328     constexpr size_t u8size = 256;
329     std::vector<uint8_t> u8ref(u8size);
330     std::vector<uint8_t> u8ary(u8size);
331 
332     for (size_t i = 0; i < u8ref.size(); ++i) {
333         u8ref[i] = i;
334     }
335 
336     constexpr size_t testsize = std::min(u8size, size);
337     zeroFill(fary);
338     memcpy_to_float_from_u8(fary.data(), u8ref.data(), testsize);
339     memcpy_to_u8_from_float(u8ary.data(), fary.data(), testsize);
340 
341     EXPECT_EQ(0, memcmp(u8ary.data(), u8ref.data(), u8ary.size() * sizeof(u8ary[0])));
342 
343     // test conversion from u8 to i32
344     zeroFill(i32ary);
345     memcpy_to_i32_from_u8(i32ary.data(), u8ref.data(), testsize);
346     checkMonotone(i32ary.data(), testsize);
347 }
348 
349 template<typename T>
checkMonotoneOrZero(const T * ary,size_t size)350 void checkMonotoneOrZero(const T *ary, size_t size)
351 {
352     T least = 0;
353 
354     for (size_t i = 1; i < size; ++i) {
355         if (ary[i]) {
356             EXPECT_LT(least, ary[i]);
357             least = ary[i];
358         }
359     }
360 }
361 
TEST(audio_utils_primitives,memcpy_by_channel_mask)362 TEST(audio_utils_primitives, memcpy_by_channel_mask) {
363     uint32_t dst_mask;
364     uint32_t src_mask;
365     uint16_t *u16ref = new uint16_t[65536];
366     uint16_t *u16ary = new uint16_t[65536];
367 
368     for (size_t i = 0; i < 65536; ++i) {
369         u16ref[i] = i;
370     }
371 
372     // Test when src mask is 0.  Everything copied is zero.
373     src_mask = 0;
374     dst_mask = 0x8d;
375     memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
376     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
377             65536 / __builtin_popcount(dst_mask));
378     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
379 
380     // Test when dst_mask is 0.  Nothing should be copied.
381     src_mask = 0;
382     dst_mask = 0;
383     memset(u16ary, 0, 65536 * sizeof(u16ref[0]));
384     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
385             65536);
386     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
387 
388     // Test when masks are the same.  One to one copy.
389     src_mask = dst_mask = 0x8d;
390     memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
391     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
392     EXPECT_EQ(0, memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * __builtin_popcount(dst_mask)));
393 
394     // Test with a gap in source:
395     // Input 3 samples, output 4 samples, one zero inserted.
396     src_mask = 0x8c;
397     dst_mask = 0x8d;
398     memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
399     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
400             65536 / __builtin_popcount(dst_mask));
401     checkMonotoneOrZero(u16ary, 65536);
402     EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
403 
404     // Test with a gap in destination:
405     // Input 4 samples, output 3 samples, one deleted
406     src_mask = 0x8d;
407     dst_mask = 0x8c;
408     memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
409     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
410             65536 / __builtin_popcount(src_mask));
411     checkMonotone(u16ary, 65536 * 3 / 4);
412 
413     delete[] u16ref;
414     delete[] u16ary;
415 }
416 
memcpy_by_channel_mask2(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)417 void memcpy_by_channel_mask2(void *dst, uint32_t dst_mask,
418         const void *src, uint32_t src_mask, size_t sample_size, size_t count)
419 {
420     int8_t idxary[32];
421     uint32_t src_channels = __builtin_popcount(src_mask);
422     uint32_t dst_channels =
423             memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
424 
425     memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
426 }
427 
428 // a modified version of the memcpy_by_channel_mask test
429 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array)430 TEST(audio_utils_primitives, memcpy_by_index_array) {
431     uint32_t dst_mask;
432     uint32_t src_mask;
433     typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
434     uint8x3_t *u24ref = new uint8x3_t[65536];
435     uint8x3_t *u24ary = new uint8x3_t[65536];
436     uint16_t *u16ref = new uint16_t[65536];
437     uint16_t *u16ary = new uint16_t[65536];
438 
439     EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
440 
441     // tests prepare_index_array_from_masks()
442     EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c));
443     EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d));
444 
445     for (size_t i = 0; i < 65536; ++i) {
446         u16ref[i] = i;
447     }
448     memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
449 
450     // Test when src mask is 0.  Everything copied is zero.
451     src_mask = 0;
452     dst_mask = 0x8d;
453     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
454     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
455             65536 / __builtin_popcount(dst_mask));
456     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
457     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
458 
459     // Test when dst_mask is 0.  Nothing should be copied.
460     src_mask = 0;
461     dst_mask = 0;
462     memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
463     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
464             65536);
465     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
466     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
467 
468     // Test when masks are the same.  One to one copy.
469     src_mask = dst_mask = 0x8d;
470     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
471     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
472     EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
473 
474     // Test with a gap in source:
475     // Input 3 samples, output 4 samples, one zero inserted.
476     src_mask = 0x8c;
477     dst_mask = 0x8d;
478     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
479     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
480             65536 / __builtin_popcount(dst_mask));
481     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
482     checkMonotoneOrZero(u16ary, 65536);
483     EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
484 
485     // Test with a gap in destination:
486     // Input 4 samples, output 3 samples, one deleted
487     src_mask = 0x8d;
488     dst_mask = 0x8c;
489     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
490     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
491             65536 / __builtin_popcount(src_mask));
492     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
493     checkMonotone(u16ary, 65536 * 3 / 4);
494 
495     delete[] u16ref;
496     delete[] u16ary;
497     delete[] u24ref;
498     delete[] u24ary;
499 }
500 
memcpy_by_channel_mask_dst_index(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)501 void memcpy_by_channel_mask_dst_index(void *dst, uint32_t dst_mask,
502         const void *src, uint32_t src_mask, size_t sample_size, size_t count)
503 {
504     int8_t idxary[32];
505     uint32_t src_channels = __builtin_popcount(src_mask);
506     uint32_t dst_channels =
507             memcpy_by_index_array_initialization_dst_index(idxary, 32, dst_mask, src_mask);
508 
509     memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
510 }
511 
512 // a modified version of the memcpy_by_channel_mask test
513 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_dst_index)514 TEST(audio_utils_primitives, memcpy_by_index_array_dst_index) {
515     uint32_t dst_mask;
516     uint32_t src_mask;
517     typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
518     uint8x3_t *u24ref = new uint8x3_t[65536];
519     uint8x3_t *u24ary = new uint8x3_t[65536];
520     uint16_t *u16ref = new uint16_t[65536];
521     uint16_t *u16ary = new uint16_t[65536];
522 
523     EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
524 
525     // tests prepare_index_array_from_masks()
526     EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8d, 0x8c));
527     EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8c, 0x8d));
528 
529     for (size_t i = 0; i < 65536; ++i) {
530         u16ref[i] = i;
531     }
532     memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
533 
534     // Test when src mask is 0.  Everything copied is zero.
535     src_mask = 0;
536     dst_mask = 0x8d;
537     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
538     memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
539             65536 / __builtin_popcount(dst_mask));
540     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
541     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
542 
543     // Test when dst_mask is 0.  Nothing should be copied.
544     src_mask = 0;
545     dst_mask = 0;
546     memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
547     memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
548             65536);
549     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
550     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
551 
552     // Test when dst mask equals source count size.  One to one copy.
553     src_mask = 0x8d;
554     dst_mask = 0x0f;
555     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
556     memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
557     EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
558 
559     // Test with a gap in source:
560     // Input 3 samples, output 4 samples, one zero inserted.
561     src_mask = 0x8c;
562     dst_mask = 0x0f;
563     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
564     memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
565             65536 / __builtin_popcount(dst_mask));
566     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
567     checkMonotoneOrZero(u16ary, 65536);
568     EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
569 
570     // Test with a gap in destination:
571     // Input 4 samples, output 3 samples, one deleted
572     src_mask = 0x8d;
573     dst_mask = 0x07;
574     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
575     memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
576             65536 / __builtin_popcount(src_mask));
577     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
578     checkMonotone(u16ary, 65536 * 3 / 4);
579 
580     delete[] u16ref;
581     delete[] u16ary;
582     delete[] u24ref;
583     delete[] u24ary;
584 }
585 
memcpy_by_channel_mask_src_index(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)586 void memcpy_by_channel_mask_src_index(void *dst, uint32_t dst_mask,
587         const void *src, uint32_t src_mask, size_t sample_size, size_t count)
588 {
589     int8_t idxary[32];
590     uint32_t src_channels = __builtin_popcount(src_mask);
591     uint32_t dst_channels =
592             memcpy_by_index_array_initialization_src_index(idxary, 32, dst_mask, src_mask);
593 
594     memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
595 }
596 
597 // a modified version of the memcpy_by_channel_mask test
598 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_src_index)599 TEST(audio_utils_primitives, memcpy_by_index_array_src_index) {
600     uint32_t dst_mask;
601     uint32_t src_mask;
602     typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
603     uint8x3_t *u24ref = new uint8x3_t[65536];
604     uint8x3_t *u24ary = new uint8x3_t[65536];
605     uint16_t *u16ref = new uint16_t[65536];
606     uint16_t *u16ary = new uint16_t[65536];
607 
608     EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
609 
610     // tests prepare_index_array_from_masks()
611     EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8d, 0x8c));
612     EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8c, 0x8d));
613 
614     for (size_t i = 0; i < 65536; ++i) {
615         u16ref[i] = i;
616     }
617     memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
618 
619     // Test when src mask is 0.  Everything copied is zero.
620     src_mask = 0;
621     dst_mask = 0x8d;
622     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
623     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
624             65536 / __builtin_popcount(dst_mask));
625     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
626     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
627 
628     // Test when dst_mask is 0.  Nothing should be copied.
629     src_mask = 0;
630     dst_mask = 0;
631     memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
632     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
633             65536);
634     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
635     EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
636 
637     // Test when source mask must copy to dst mask.  One to one copy.
638     src_mask = 0xf;
639     dst_mask = 0xf;
640     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
641     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
642     EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
643 
644     // Test when source mask must copy to dst mask.  One to one copy.
645     src_mask = 0xf;
646     dst_mask = 0x8d;
647     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
648     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
649     EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * __builtin_popcount(dst_mask)));
650 
651     // Test with a gap in source:
652     // Input 3 samples, output 4 samples, one zero inserted.
653     src_mask = 0x07;
654     dst_mask = 0x8d;
655     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
656     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
657             65536 / __builtin_popcount(dst_mask));
658     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
659     checkMonotoneOrZero(u16ary, 65536);
660     EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
661 
662     // Test with a gap in destination:
663     // Input 4 samples, output 3 samples, one deleted
664     src_mask = 0x0f;
665     dst_mask = 0x8c;
666     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
667     memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
668             65536 / __builtin_popcount(src_mask));
669     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
670     checkMonotone(u16ary, 65536 * 3 / 4);
671 
672     delete[] u16ref;
673     delete[] u16ary;
674     delete[] u24ref;
675     delete[] u24ary;
676 }
677 
TEST(audio_utils_primitives,updown_mix)678 TEST(audio_utils_primitives, updown_mix) {
679     const size_t size = 32767;
680     std::vector<int16_t> i16ref(size * 2);
681     std::vector<int16_t> i16ary(size * 2);
682 
683     for (size_t i = 0; i < size; ++i) {
684         i16ref[i] = i;
685     }
686     upmix_to_stereo_i16_from_mono_i16(i16ary.data(), i16ref.data(), size);
687     downmix_to_mono_i16_from_stereo_i16(i16ary.data(), i16ary.data(), size);
688 
689     EXPECT_EQ(0, memcmp(i16ary.data(), i16ref.data(), sizeof(i16ref[0]) * size));
690 }
691 
692 template<typename T, typename TComparison>
checkAddedClamped(T * out,const T * in1,const T * in2,size_t size,TComparison limNeg,TComparison limPos)693 void checkAddedClamped(T *out, const T *in1, const T *in2, size_t size,
694         TComparison limNeg, TComparison limPos)
695 {
696     for (size_t i = 0; i < size; ++i) {
697         TComparison added = (TComparison)in1[i] + in2[i];
698         if (added <= limNeg) {
699             EXPECT_EQ(limNeg, out[i]);
700         } else if (added >= limPos) {
701             EXPECT_EQ(limPos, out[i]);
702         } else {
703             EXPECT_EQ(added, out[i]);
704         }
705     }
706 }
707 
checkAddedClampedp24(uint8_t * pary,const uint8_t * in1,const uint8_t * in2,size_t size)708 void checkAddedClampedp24(uint8_t *pary, const uint8_t *in1,
709         const uint8_t *in2, size_t size) {
710     // Convert to q8_23 for comparison.
711     int32_t *outi32ary = new int32_t[size];
712     int32_t *in1i32ary = new int32_t[size];
713     int32_t *in2i32ary = new int32_t[size];
714     memcpy_to_q8_23_from_p24(outi32ary, pary, size);
715     memcpy_to_q8_23_from_p24(in1i32ary, in1, size);
716     memcpy_to_q8_23_from_p24(in2i32ary, in2, size);
717     checkAddedClamped(
718             outi32ary, in1i32ary, in2i32ary, size, lim24neg, lim24pos);
719     delete[] in2i32ary;
720     delete[] in1i32ary;
721     delete[] outi32ary;
722 }
723 
checkAddedClampedu8(uint8_t * out,const uint8_t * in1,const uint8_t * in2,size_t size)724 void checkAddedClampedu8(uint8_t *out, const uint8_t *in1,
725         const uint8_t *in2, size_t size) {
726     // uint8_t data is centered around 0x80, not 0, so checkAddedClamped
727     // won't work. Convert to i16 first.
728     int16_t *outi16ary = new int16_t[size];
729     int16_t *in1i16ary = new int16_t[size];
730     int16_t *in2i16ary = new int16_t[size];
731     memcpy_to_i16_from_u8(outi16ary, out, size);
732     memcpy_to_i16_from_u8(in1i16ary, in1, size);
733     memcpy_to_i16_from_u8(in2i16ary, in2, size);
734     // Only the higher order bits are used.
735     checkAddedClamped(outi16ary, in1i16ary, in2i16ary, size,
736             -0x8000, 0x7f00);
737     delete[] in2i16ary;
738     delete[] in1i16ary;
739     delete[] outi16ary;
740 }
741 
TEST(audio_utils_primitives,accumulate)742 TEST(audio_utils_primitives, accumulate) {
743     int16_t *i16ref = new int16_t[65536];
744     int16_t *i16add = new int16_t[65536];
745     int16_t *i16ary = new int16_t[65536];
746 
747     for (size_t i = 0; i < 65536; ++i) {
748         i16ref[i] = i16ary[i] = i16add[(i+1) % 65536] = i - 32768;
749     }
750 
751     // Test i16.
752     accumulate_i16(i16ary, i16add, 65536);
753     checkAddedClamped(i16ary, i16ref, i16add, 65536, lim16neg,
754             lim16pos);
755 
756     // Test i32.
757     int32_t *i32ary = new int32_t[65536];
758     int32_t *i32add = new int32_t[65536];
759     int32_t *i32ref = new int32_t[65536];
760     // Convert sample data to i32 to perform accumulate function.
761     memcpy_to_i32_from_i16(i32ary, i16ref, 65536);
762     memcpy_to_i32_from_i16(i32add, i16add, 65536);
763     // Ensure the reference matches the inital output after conversion.
764     memcpy(i32ref, i32ary, 65536 * sizeof(i32ary[0]));
765     // Accumulate and check.
766     accumulate_i32(i32ary, i32add, 65536);
767     checkAddedClamped(
768             i32ary, i32ref, i32add, 65536, lim32neg, lim32pos);
769     // Cleanup
770     delete[] i32ref;
771     delete[] i32add;
772     delete[] i32ary;
773 
774     // Test u8.
775     uint8_t *u8ary = new uint8_t[65536];
776     uint8_t *u8add = new uint8_t[65536];
777     uint8_t *u8ref = new uint8_t[65536];
778     // Convert sample data to u8 to perform accumulate function.
779     memcpy_to_u8_from_i16(u8ary, i16ref, 65536);
780     memcpy_to_u8_from_i16(u8add, i16add, 65536);
781     // Ensure the reference matches the inital output after conversion.
782     memcpy(u8ref, u8ary, 65536 * sizeof(u8ary[0]));
783     // Accumulate and check.
784     accumulate_u8(u8ary, u8add, 65536);
785     checkAddedClampedu8(u8ary, u8ref, u8add, 65536);
786     // Cleanup.
787     delete[] u8ref;
788     delete[] u8add;
789     delete[] u8ary;
790 
791     // Test 24 bit packed.
792     uint8_t *pary = new uint8_t[65536 * 3];
793     uint8_t *padd = new uint8_t[65536 * 3];
794     uint8_t *pref = new uint8_t[65536 * 3];
795     // Convert sample data to p24 to perform accumulate function.
796     memcpy_to_p24_from_i16(pary, i16ref, 65536);
797     memcpy_to_p24_from_i16(padd, i16add, 65536);
798     // Ensure the reference matches the inital output after conversion.
799     memcpy(pref, pary, 65536 * sizeof(pary[0]) * 3);
800     // Accumulate and check.
801     accumulate_p24(pary, padd, 65536);
802     checkAddedClampedp24(pary, pref, padd, 65536);
803     // Cleanup.
804     delete[] pref;
805     delete[] padd;
806     delete[] pary;
807 
808     // Test 24 bit unpacked.
809     int32_t *q8_23ary = new int32_t[65536];
810     int32_t *q8_23add = new int32_t[65536];
811     int32_t *q8_23ref = new int32_t[65536];
812     // Convert sample data to q8_23 to perform accumulate function.
813     memcpy_to_q8_23_from_i16(q8_23ary, i16ref, 65536);
814     memcpy_to_q8_23_from_i16(q8_23add, i16add, 65536);
815     // Ensure the reference matches the inital output after conversion.
816     memcpy(q8_23ref, q8_23ary, 65536 * sizeof(q8_23ary[0]));
817     // Accumulate and check.
818     accumulate_q8_23(q8_23ary, q8_23add, 65536);
819     checkAddedClamped(
820             q8_23ary, q8_23ref, q8_23add, 65536, lim24neg, lim24pos);
821     // Cleanup.
822     delete[] q8_23ref;
823     delete[] q8_23add;
824     delete[] q8_23ary;
825 
826     // Test float.
827     float *fary = new float[65536];
828     float *fadd = new float[65536];
829     float *fref = new float[65536];
830     // Convert sample data to float to perform accumulate function.
831     memcpy_to_float_from_i16(fary, i16ref, 65536);
832     memcpy_to_float_from_i16(fadd, i16add, 65536);
833     // Ensure the reference matches the inital output after conversion.
834     memcpy(fref, fary, 65536 * sizeof(fary[0]));
835     // Accumulate and check. Floats aren't clamped by accumulate,
836     // but given the input is in the [-1.0, 1.0) range output should be in
837     // [-2.0, 2.0) range.
838     accumulate_float(fary, fadd, 65536);
839     checkAddedClamped(fary, fref, fadd, 65536, -2.0f, 2.0f);
840     // Cleanup.
841     delete[] fref;
842     delete[] fadd;
843     delete[] fary;
844 
845     delete[] i16ary;
846     delete[] i16add;
847     delete[] i16ref;
848 }
849 
850 
TEST(audio_utils_primitives,MemcpyToFloatFromFloatWithClamping)851 TEST(audio_utils_primitives, MemcpyToFloatFromFloatWithClamping) {
852     std::vector<float> src = {-INFINITY, -2, -1, -0, 0, 0.009, 1.000001, 9999999, INFINITY, NAN};
853     std::vector<float> dst(src.size());
854     float absMax = 1;
855     std::vector<float> expected = {-1, -1, -1, -0, 0, 0.009, 1, 1, 1, 1};
856     ASSERT_EQ(expected.size(), src.size());
857 
858     memcpy_to_float_from_float_with_clamping(dst.data(), src.data(), src.size(), absMax);
859 
860     ASSERT_EQ(dst, expected) << "src=" << testing::PrintToString(src);
861 }
862