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