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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "audio_utils_primitives_tests"
19
20 #include <math.h>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24 #include <log/log.h>
25
26 #include <audio_utils/primitives.h>
27 #include <audio_utils/format.h>
28 #include <audio_utils/channels.h>
29
30 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
31
32 static const int32_t lim8pos = 255;
33 static const int32_t lim8neg = 0;
34 static const int32_t lim16pos = (1 << 15) - 1;
35 static const int32_t lim16neg = -(1 << 15);
36 static const int32_t lim24pos = (1 << 23) - 1;
37 static const int32_t lim24neg = -(1 << 23);
38
testClamp8(float f)39 inline void testClamp8(float f)
40 {
41 // f is in native u8 scaling to test rounding
42 uint8_t uval = clamp8_from_float((f - 128) / (1 << 7));
43
44 // test clamping
45 ALOGV("clamp8_from_float(%f) = %u\n", f, uval);
46 if (f > lim8pos) {
47 EXPECT_EQ(lim8pos, uval);
48 } else if (f < lim8neg) {
49 EXPECT_EQ(lim8neg, uval);
50 }
51
52 // if in range, make sure round trip clamp and conversion is correct.
53 if (f < lim8pos - 1. && f > lim8neg + 1.) {
54 uint8_t uval2 = clamp8_from_float(float_from_u8(uval));
55 int diff = abs(uval - uval2);
56 EXPECT_LE(diff, 1);
57 }
58 }
59
testClamp16(float f)60 inline void testClamp16(float f)
61 {
62 int16_t ival = clamp16_from_float(f / (1 << 15));
63
64 // test clamping
65 ALOGV("clamp16_from_float(%f) = %d\n", f, ival);
66 if (f > lim16pos) {
67 EXPECT_EQ(lim16pos, ival);
68 } else if (f < lim16neg) {
69 EXPECT_EQ(lim16neg, ival);
70 }
71
72 // if in range, make sure round trip clamp and conversion is correct.
73 if (f < lim16pos - 1. && f > lim16neg + 1.) {
74 int ival2 = clamp16_from_float(float_from_i16(ival));
75 int diff = abs(ival - ival2);
76 EXPECT_LE(diff, 1);
77 }
78 }
79
testClamp24(float f)80 inline void testClamp24(float f)
81 {
82 int32_t ival = clamp24_from_float(f / (1 << 23));
83
84 // test clamping
85 ALOGV("clamp24_from_float(%f) = %d\n", f, ival);
86 if (f > lim24pos) {
87 EXPECT_EQ(lim24pos, ival);
88 } else if (f < lim24neg) {
89 EXPECT_EQ(lim24neg, ival);
90 }
91
92 // if in range, make sure round trip clamp and conversion is correct.
93 if (f < lim24pos - 1. && f > lim24neg + 1.) {
94 int ival2 = clamp24_from_float(float_from_q8_23(ival));
95 int diff = abs(ival - ival2);
96 EXPECT_LE(diff, 1);
97 }
98 }
99
100 template<typename T>
checkMonotone(const T * ary,size_t size)101 void checkMonotone(const T *ary, size_t size)
102 {
103 for (size_t i = 1; i < size; ++i) {
104 EXPECT_LT(ary[i-1], ary[i]);
105 }
106 }
107
checkMonotonep24(uint8_t * pary,size_t size)108 void checkMonotonep24(uint8_t * pary, size_t size)
109 {
110 size_t frames = size/3;
111 for (size_t i = 1; i < frames; ++i) {
112 EXPECT_LT(i32_from_p24(pary + 3*(i-1)), i32_from_p24(pary + 3*i));
113 }
114 }
115
TEST(audio_utils_primitives,clamp_to_int)116 TEST(audio_utils_primitives, clamp_to_int) {
117 static const float testArray[] = {
118 -NAN, -INFINITY,
119 -1.e20, -32768., 63.9,
120 -3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
121 1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
122 32767., 32768., 1.e20,
123 INFINITY, NAN };
124
125 for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
126 testClamp8(testArray[i]);
127 }
128 for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
129 testClamp16(testArray[i]);
130 }
131 for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
132 testClamp24(testArray[i]);
133 }
134
135 // used for ULP testing (tweaking the lsb of the float)
136 union {
137 int32_t i;
138 float f;
139 } val;
140 int32_t res;
141
142 // check clampq4_27_from_float()
143 val.f = 16.;
144 res = clampq4_27_from_float(val.f);
145 EXPECT_EQ(0x7fffffff, res);
146 val.i--;
147 res = clampq4_27_from_float(val.f);
148 EXPECT_LE(res, 0x7fffffff);
149 EXPECT_GE(res, 0x7fff0000);
150 val.f = -16.;
151 res = clampq4_27_from_float(val.f);
152 EXPECT_EQ((int32_t)0x80000000, res); // negative
153 val.i++;
154 res = clampq4_27_from_float(val.f);
155 EXPECT_GE(res, (int32_t)0x80000000); // negative
156 EXPECT_LE(res, (int32_t)0x80008000); // negative
157
158 // check u4_28_from_float and u4_12_from_float
159 uint32_t ures;
160 uint16_t ures16;
161 val.f = 16.;
162 ures = u4_28_from_float(val.f);
163 EXPECT_EQ(0xffffffff, ures);
164 ures16 = u4_12_from_float(val.f);
165 EXPECT_EQ(0xffff, ures16);
166
167 val.f = -1.;
168 ures = u4_28_from_float(val.f);
169 EXPECT_EQ((uint32_t)0, ures);
170 ures16 = u4_12_from_float(val.f);
171 EXPECT_EQ(0, ures16);
172
173 // check float_from_u4_28 and float_from_u4_12 (roundtrip)
174 for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
175 ures = u4_28_from_float(float_from_u4_28(v));
176 EXPECT_EQ(ures, v);
177 }
178 for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
179 ures16 = u4_12_from_float(float_from_u4_12(v));
180 EXPECT_EQ(ures16, v);
181 }
182
183 // check infinity
184 EXPECT_EQ(0, clamp8_from_float(-INFINITY));
185 EXPECT_EQ(255, clamp8_from_float(INFINITY));
186 }
187
TEST(audio_utils_primitives,memcpy)188 TEST(audio_utils_primitives, memcpy) {
189 // test round-trip.
190 int16_t *i16ref = new int16_t[65536];
191 int16_t *i16ary = new int16_t[65536];
192 int32_t *i32ary = new int32_t[65536];
193 float *fary = new float[65536];
194 uint8_t *pary = new uint8_t[65536*3];
195
196 for (size_t i = 0; i < 65536; ++i) {
197 i16ref[i] = i16ary[i] = i - 32768;
198 }
199
200 // do round-trip testing i16 and float
201 memcpy_to_float_from_i16(fary, i16ary, 65536);
202 memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
203 checkMonotone(fary, 65536);
204
205 memcpy_to_i16_from_float(i16ary, fary, 65536);
206 memset(fary, 0, 65536 * sizeof(fary[0]));
207 checkMonotone(i16ary, 65536);
208
209 // TODO make a template case for the following?
210
211 // do round-trip testing p24 to i16 and float
212 memcpy_to_p24_from_i16(pary, i16ary, 65536);
213 memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
214
215 // check an intermediate format at a position(???)
216 #if 0
217 printf("pary[%d].0 = %u pary[%d].1 = %u pary[%d].2 = %u\n",
218 1025, (unsigned) pary[1025*3],
219 1025, (unsigned) pary[1025*3+1],
220 1025, (unsigned) pary[1025*3+2]
221 );
222 #endif
223
224 memcpy_to_float_from_p24(fary, pary, 65536);
225 memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
226 checkMonotone(fary, 65536);
227
228 memcpy_to_p24_from_float(pary, fary, 65536);
229 memset(fary, 0, 65536 * sizeof(fary[0]));
230
231 memcpy_to_i16_from_p24(i16ary, pary, 65536);
232 memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
233 checkMonotone(i16ary, 65536);
234
235 // do round-trip testing q8_23 to i16 and float
236 memcpy_to_q8_23_from_i16(i32ary, i16ary, 65536);
237 memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
238 checkMonotone(i32ary, 65536);
239
240 memcpy_to_float_from_q8_23(fary, i32ary, 65536);
241 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
242 checkMonotone(fary, 65536);
243
244 memcpy_to_q8_23_from_float_with_clamp(i32ary, fary, 65536);
245 memset(fary, 0, 65536 * sizeof(fary[0]));
246 checkMonotone(i32ary, 65536);
247
248 memcpy_to_i16_from_q8_23(i16ary, i32ary, 65536);
249 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
250 checkMonotone(i16ary, 65536);
251
252 // do round-trip testing i32 to i16 and float
253 memcpy_to_i32_from_i16(i32ary, i16ary, 65536);
254 memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
255 checkMonotone(i32ary, 65536);
256
257 memcpy_to_float_from_i32(fary, i32ary, 65536);
258 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
259 checkMonotone(fary, 65536);
260
261 memcpy_to_i32_from_float(i32ary, fary, 65536);
262 memset(fary, 0, 65536 * sizeof(fary[0]));
263 checkMonotone(i32ary, 65536);
264
265 memcpy_to_i16_from_i32(i16ary, i32ary, 65536);
266 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
267 checkMonotone(i16ary, 65536);
268
269 // do round-trip test i16 -> p24 -> i32 -> p24 -> q8_23 -> p24 -> i16
270 memcpy_to_p24_from_i16(pary, i16ary, 65536);
271 memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
272 checkMonotonep24(pary, 65536 * 3);
273
274 memcpy_to_i32_from_p24(i32ary, pary, 65536);
275 memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
276 checkMonotone(i32ary, 65536);
277
278 memcpy_to_p24_from_i32(pary, i32ary, 65536);
279 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
280 checkMonotonep24(pary, 65536 * 3);
281
282 memcpy_to_q8_23_from_p24(i32ary, pary, 65536);
283 memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
284 checkMonotone(i32ary, 65536);
285
286 memcpy_to_p24_from_q8_23(pary, i32ary, 65536);
287 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
288 checkMonotonep24(pary, 65536 * 3);
289
290 memcpy_to_i16_from_p24(i16ary, pary, 65536);
291 memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
292 checkMonotone(i16ary, 65536);
293
294 // do partial round-trip testing q4_27 to i16 and float
295 memcpy_to_float_from_i16(fary, i16ary, 65536);
296 //memset(i16ary, 0, 65536 * sizeof(i16ary[0])); // not cleared: we don't do full roundtrip
297
298 memcpy_to_q4_27_from_float(i32ary, fary, 65536);
299 memset(fary, 0, 65536 * sizeof(fary[0]));
300 checkMonotone(i32ary, 65536);
301
302 memcpy_to_float_from_q4_27(fary, i32ary, 65536);
303 memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
304 checkMonotone(fary, 65536);
305
306 // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
307 EXPECT_EQ(0, memcmp(i16ary, i16ref, 65536*sizeof(i16ary[0])));
308
309 // test round-trip for u8 and float.
310 uint8_t *u8ref = new uint8_t[256];
311 uint8_t *u8ary = new uint8_t[256];
312
313 for (unsigned i = 0; i < 256; ++i) {
314 u8ref[i] = i;
315 }
316
317 memcpy_to_float_from_u8(fary, u8ref, 256);
318 memcpy_to_u8_from_float(u8ary, fary, 256);
319
320 EXPECT_EQ(0, memcmp(u8ary, u8ref, 256 * sizeof(u8ary[0])));
321
322 delete[] u8ref;
323 delete[] u8ary;
324 delete[] i16ref;
325 delete[] i16ary;
326 delete[] i32ary;
327 delete[] fary;
328 delete[] pary;
329 }
330
331 template<typename T>
checkMonotoneOrZero(const T * ary,size_t size)332 void checkMonotoneOrZero(const T *ary, size_t size)
333 {
334 T least = 0;
335
336 for (size_t i = 1; i < size; ++i) {
337 if (ary[i]) {
338 EXPECT_LT(least, ary[i]);
339 least = ary[i];
340 }
341 }
342 }
343
TEST(audio_utils_primitives,memcpy_by_channel_mask)344 TEST(audio_utils_primitives, memcpy_by_channel_mask) {
345 uint32_t dst_mask;
346 uint32_t src_mask;
347 uint16_t *u16ref = new uint16_t[65536];
348 uint16_t *u16ary = new uint16_t[65536];
349
350 for (size_t i = 0; i < 65536; ++i) {
351 u16ref[i] = i;
352 }
353
354 // Test when src mask is 0. Everything copied is zero.
355 src_mask = 0;
356 dst_mask = 0x8d;
357 memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
358 memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
359 65536 / popcount(dst_mask));
360 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
361
362 // Test when dst_mask is 0. Nothing should be copied.
363 src_mask = 0;
364 dst_mask = 0;
365 memset(u16ary, 0, 65536 * sizeof(u16ref[0]));
366 memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
367 65536);
368 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
369
370 // Test when masks are the same. One to one copy.
371 src_mask = dst_mask = 0x8d;
372 memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
373 memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
374 EXPECT_EQ(0, memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * popcount(dst_mask)));
375
376 // Test with a gap in source:
377 // Input 3 samples, output 4 samples, one zero inserted.
378 src_mask = 0x8c;
379 dst_mask = 0x8d;
380 memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
381 memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
382 65536 / popcount(dst_mask));
383 checkMonotoneOrZero(u16ary, 65536);
384 EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
385
386 // Test with a gap in destination:
387 // Input 4 samples, output 3 samples, one deleted
388 src_mask = 0x8d;
389 dst_mask = 0x8c;
390 memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
391 memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
392 65536 / popcount(src_mask));
393 checkMonotone(u16ary, 65536 * 3 / 4);
394
395 delete[] u16ref;
396 delete[] u16ary;
397 }
398
memcpy_by_channel_mask2(void * dst,uint32_t dst_mask,const void * src,uint32_t src_mask,size_t sample_size,size_t count)399 void memcpy_by_channel_mask2(void *dst, uint32_t dst_mask,
400 const void *src, uint32_t src_mask, size_t sample_size, size_t count)
401 {
402 int8_t idxary[32];
403 uint32_t src_channels = popcount(src_mask);
404 uint32_t dst_channels =
405 memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
406
407 memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
408 }
409
410 // a modified version of the memcpy_by_channel_mask test
411 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array)412 TEST(audio_utils_primitives, memcpy_by_index_array) {
413 uint32_t dst_mask;
414 uint32_t src_mask;
415 typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
416 uint8x3_t *u24ref = new uint8x3_t[65536];
417 uint8x3_t *u24ary = new uint8x3_t[65536];
418 uint16_t *u16ref = new uint16_t[65536];
419 uint16_t *u16ary = new uint16_t[65536];
420
421 EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
422
423 // tests prepare_index_array_from_masks()
424 EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c));
425 EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d));
426
427 for (size_t i = 0; i < 65536; ++i) {
428 u16ref[i] = i;
429 }
430 memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
431
432 // Test when src mask is 0. Everything copied is zero.
433 src_mask = 0;
434 dst_mask = 0x8d;
435 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
436 memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
437 65536 / popcount(dst_mask));
438 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
439 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
440
441 // Test when dst_mask is 0. Nothing should be copied.
442 src_mask = 0;
443 dst_mask = 0;
444 memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
445 memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
446 65536);
447 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
448 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
449
450 // Test when masks are the same. One to one copy.
451 src_mask = dst_mask = 0x8d;
452 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
453 memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
454 EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
455
456 // Test with a gap in source:
457 // Input 3 samples, output 4 samples, one zero inserted.
458 src_mask = 0x8c;
459 dst_mask = 0x8d;
460 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
461 memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
462 65536 / popcount(dst_mask));
463 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
464 checkMonotoneOrZero(u16ary, 65536);
465 EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
466
467 // Test with a gap in destination:
468 // Input 4 samples, output 3 samples, one deleted
469 src_mask = 0x8d;
470 dst_mask = 0x8c;
471 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
472 memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
473 65536 / popcount(src_mask));
474 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
475 checkMonotone(u16ary, 65536 * 3 / 4);
476
477 delete[] u16ref;
478 delete[] u16ary;
479 delete[] u24ref;
480 delete[] u24ary;
481 }
482
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)483 void memcpy_by_channel_mask_dst_index(void *dst, uint32_t dst_mask,
484 const void *src, uint32_t src_mask, size_t sample_size, size_t count)
485 {
486 int8_t idxary[32];
487 uint32_t src_channels = popcount(src_mask);
488 uint32_t dst_channels =
489 memcpy_by_index_array_initialization_dst_index(idxary, 32, dst_mask, src_mask);
490
491 memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
492 }
493
494 // a modified version of the memcpy_by_channel_mask test
495 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_dst_index)496 TEST(audio_utils_primitives, memcpy_by_index_array_dst_index) {
497 uint32_t dst_mask;
498 uint32_t src_mask;
499 typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
500 uint8x3_t *u24ref = new uint8x3_t[65536];
501 uint8x3_t *u24ary = new uint8x3_t[65536];
502 uint16_t *u16ref = new uint16_t[65536];
503 uint16_t *u16ary = new uint16_t[65536];
504
505 EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
506
507 // tests prepare_index_array_from_masks()
508 EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8d, 0x8c));
509 EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_dst_index(NULL, 0, 0x8c, 0x8d));
510
511 for (size_t i = 0; i < 65536; ++i) {
512 u16ref[i] = i;
513 }
514 memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
515
516 // Test when src mask is 0. Everything copied is zero.
517 src_mask = 0;
518 dst_mask = 0x8d;
519 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
520 memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
521 65536 / popcount(dst_mask));
522 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
523 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
524
525 // Test when dst_mask is 0. Nothing should be copied.
526 src_mask = 0;
527 dst_mask = 0;
528 memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
529 memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
530 65536);
531 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
532 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
533
534 // Test when dst mask equals source count size. One to one copy.
535 src_mask = 0x8d;
536 dst_mask = 0x0f;
537 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
538 memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
539 EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
540
541 // Test with a gap in source:
542 // Input 3 samples, output 4 samples, one zero inserted.
543 src_mask = 0x8c;
544 dst_mask = 0x0f;
545 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
546 memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
547 65536 / popcount(dst_mask));
548 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
549 checkMonotoneOrZero(u16ary, 65536);
550 EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
551
552 // Test with a gap in destination:
553 // Input 4 samples, output 3 samples, one deleted
554 src_mask = 0x8d;
555 dst_mask = 0x07;
556 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
557 memcpy_by_channel_mask_dst_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
558 65536 / popcount(src_mask));
559 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
560 checkMonotone(u16ary, 65536 * 3 / 4);
561
562 delete[] u16ref;
563 delete[] u16ary;
564 delete[] u24ref;
565 delete[] u24ary;
566 }
567
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)568 void memcpy_by_channel_mask_src_index(void *dst, uint32_t dst_mask,
569 const void *src, uint32_t src_mask, size_t sample_size, size_t count)
570 {
571 int8_t idxary[32];
572 uint32_t src_channels = popcount(src_mask);
573 uint32_t dst_channels =
574 memcpy_by_index_array_initialization_src_index(idxary, 32, dst_mask, src_mask);
575
576 memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
577 }
578
579 // a modified version of the memcpy_by_channel_mask test
580 // but using 24 bit type and memcpy_by_index_array()
TEST(audio_utils_primitives,memcpy_by_index_array_src_index)581 TEST(audio_utils_primitives, memcpy_by_index_array_src_index) {
582 uint32_t dst_mask;
583 uint32_t src_mask;
584 typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
585 uint8x3_t *u24ref = new uint8x3_t[65536];
586 uint8x3_t *u24ary = new uint8x3_t[65536];
587 uint16_t *u16ref = new uint16_t[65536];
588 uint16_t *u16ary = new uint16_t[65536];
589
590 EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
591
592 // tests prepare_index_array_from_masks()
593 EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8d, 0x8c));
594 EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8c, 0x8d));
595
596 for (size_t i = 0; i < 65536; ++i) {
597 u16ref[i] = i;
598 }
599 memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
600
601 // Test when src mask is 0. Everything copied is zero.
602 src_mask = 0;
603 dst_mask = 0x8d;
604 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
605 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
606 65536 / popcount(dst_mask));
607 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
608 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
609
610 // Test when dst_mask is 0. Nothing should be copied.
611 src_mask = 0;
612 dst_mask = 0;
613 memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
614 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
615 65536);
616 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
617 EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
618
619 // Test when source mask must copy to dst mask. One to one copy.
620 src_mask = 0xf;
621 dst_mask = 0xf;
622 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
623 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
624 EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
625
626 // Test when source mask must copy to dst mask. One to one copy.
627 src_mask = 0xf;
628 dst_mask = 0x8d;
629 memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
630 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
631 EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
632
633 // Test with a gap in source:
634 // Input 3 samples, output 4 samples, one zero inserted.
635 src_mask = 0x07;
636 dst_mask = 0x8d;
637 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
638 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
639 65536 / popcount(dst_mask));
640 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
641 checkMonotoneOrZero(u16ary, 65536);
642 EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
643
644 // Test with a gap in destination:
645 // Input 4 samples, output 3 samples, one deleted
646 src_mask = 0x0f;
647 dst_mask = 0x8c;
648 memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
649 memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
650 65536 / popcount(src_mask));
651 memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
652 checkMonotone(u16ary, 65536 * 3 / 4);
653
654 delete[] u16ref;
655 delete[] u16ary;
656 delete[] u24ref;
657 delete[] u24ary;
658 }
659
TEST(audio_utils_channels,adjust_channels)660 TEST(audio_utils_channels, adjust_channels) {
661 uint16_t *u16ref = new uint16_t[65536];
662 uint16_t *u16expand = new uint16_t[65536*2];
663 uint16_t *u16ary = new uint16_t[65536];
664
665 // reference buffer always increases
666 for (size_t i = 0; i < 65536; ++i) {
667 u16ref[i] = i;
668 }
669
670 // expand channels from stereo to quad.
671 adjust_channels(u16ref /*in_buff*/, 2 /*in_channels*/,
672 u16expand /*out_buff*/, 4 /*out_channels*/,
673 sizeof(u16ref[0]) /*sample_size_in_bytes*/,
674 sizeof(u16ref[0])*65536 /*num_in_bytes*/);
675
676 // expanded buffer must increase (or be zero)
677 checkMonotoneOrZero(u16expand, 65536*2);
678
679 // contract channels back to stereo.
680 adjust_channels(u16expand /*in_buff*/, 4 /*in_channels*/,
681 u16ary /*out_buff*/, 2 /*out_channels*/,
682 sizeof(u16expand[0]) /*sample_size_in_bytes*/,
683 sizeof(u16expand[0])*65536*2 /*num_in_bytes*/);
684
685 // must be identical to original.
686 EXPECT_EQ(0, memcmp(u16ary, u16ref, sizeof(u16ref[0])*65536));
687
688 delete[] u16ref;
689 delete[] u16expand;
690 delete[] u16ary;
691 }
692