• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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