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 <vector>
     21 #include <cutils/log.h>
     22 #include <gtest/gtest.h>
     23 #include <audio_utils/primitives.h>
     24 #include <audio_utils/format.h>
     25 #include <audio_utils/channels.h>
     26 
     27 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
     28 
     29 static const int32_t lim16pos = (1 << 15) - 1;
     30 static const int32_t lim16neg = -(1 << 15);
     31 static const int32_t lim24pos = (1 << 23) - 1;
     32 static const int32_t lim24neg = -(1 << 23);
     33 
     34 inline void testClamp16(float f)
     35 {
     36     int16_t ival = clamp16_from_float(f / (1 << 15));
     37 
     38     // test clamping
     39     ALOGV("clamp16_from_float(%f) = %d\n", f, ival);
     40     if (f > lim16pos) {
     41         EXPECT_EQ(ival, lim16pos);
     42     } else if (f < lim16neg) {
     43         EXPECT_EQ(ival, lim16neg);
     44     }
     45 
     46     // if in range, make sure round trip clamp and conversion is correct.
     47     if (f < lim16pos - 1. && f > lim16neg + 1.) {
     48         int ival2 = clamp16_from_float(float_from_i16(ival));
     49         int diff = abs(ival - ival2);
     50         EXPECT_LE(diff, 1);
     51     }
     52 }
     53 
     54 inline void testClamp24(float f)
     55 {
     56     int32_t ival = clamp24_from_float(f / (1 << 23));
     57 
     58     // test clamping
     59     ALOGV("clamp24_from_float(%f) = %d\n", f, ival);
     60     if (f > lim24pos) {
     61         EXPECT_EQ(ival, lim24pos);
     62     } else if (f < lim24neg) {
     63         EXPECT_EQ(ival, lim24neg);
     64     }
     65 
     66     // if in range, make sure round trip clamp and conversion is correct.
     67     if (f < lim24pos - 1. && f > lim24neg + 1.) {
     68         int ival2 = clamp24_from_float(float_from_q8_23(ival));
     69         int diff = abs(ival - ival2);
     70         EXPECT_LE(diff, 1);
     71     }
     72 }
     73 
     74 template<typename T>
     75 void checkMonotone(const T *ary, size_t size)
     76 {
     77     for (size_t i = 1; i < size; ++i) {
     78         EXPECT_LT(ary[i-1], ary[i]);
     79     }
     80 }
     81 
     82 TEST(audio_utils_primitives, clamp_to_int) {
     83     static const float testArray[] = {
     84             -NAN, -INFINITY,
     85             -1.e20, -32768., 63.9,
     86             -3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
     87             1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
     88             32767., 32768., 1.e20,
     89             INFINITY, NAN };
     90 
     91     for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
     92         testClamp16(testArray[i]);
     93     }
     94     for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
     95         testClamp24(testArray[i]);
     96     }
     97 
     98     // used for ULP testing (tweaking the lsb of the float)
     99     union {
    100         int32_t i;
    101         float f;
    102     } val;
    103     int32_t res;
    104 
    105     // check clampq4_27_from_float()
    106     val.f = 16.;
    107     res = clampq4_27_from_float(val.f);
    108     EXPECT_EQ(res, 0x7fffffff);
    109     val.i--;
    110     res = clampq4_27_from_float(val.f);
    111     EXPECT_LE(res, 0x7fffffff);
    112     EXPECT_GE(res, 0x7fff0000);
    113     val.f = -16.;
    114     res = clampq4_27_from_float(val.f);
    115     EXPECT_EQ(res, (int32_t)0x80000000); // negative
    116     val.i++;
    117     res = clampq4_27_from_float(val.f);
    118     EXPECT_GE(res, (int32_t)0x80000000); // negative
    119     EXPECT_LE(res, (int32_t)0x80008000); // negative
    120 
    121     // check u4_28_from_float and u4_12_from_float
    122     uint32_t ures;
    123     uint16_t ures16;
    124     val.f = 16.;
    125     ures = u4_28_from_float(val.f);
    126     EXPECT_EQ(ures, 0xffffffff);
    127     ures16 = u4_12_from_float(val.f);
    128     EXPECT_EQ(ures16, 0xffff);
    129 
    130     val.f = -1.;
    131     ures = u4_28_from_float(val.f);
    132     EXPECT_EQ(ures, 0);
    133     ures16 = u4_12_from_float(val.f);
    134     EXPECT_EQ(ures16, 0);
    135 
    136     // check float_from_u4_28 and float_from_u4_12 (roundtrip)
    137     for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
    138         ures = u4_28_from_float(float_from_u4_28(v));
    139         EXPECT_EQ(ures, v);
    140     }
    141     for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
    142         ures16 = u4_12_from_float(float_from_u4_12(v));
    143         EXPECT_EQ(ures16, v);
    144     }
    145 }
    146 
    147 TEST(audio_utils_primitives, memcpy) {
    148     // test round-trip.
    149     int16_t *i16ref = new int16_t[65536];
    150     int16_t *i16ary = new int16_t[65536];
    151     int32_t *i32ary = new int32_t[65536];
    152     float *fary = new float[65536];
    153     uint8_t *pary = new uint8_t[65536*3];
    154 
    155     for (size_t i = 0; i < 65536; ++i) {
    156         i16ref[i] = i16ary[i] = i - 32768;
    157     }
    158 
    159     // do round-trip testing i16 and float
    160     memcpy_to_float_from_i16(fary, i16ary, 65536);
    161     memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    162     checkMonotone(fary, 65536);
    163 
    164     memcpy_to_i16_from_float(i16ary, fary, 65536);
    165     memset(fary, 0, 65536 * sizeof(fary[0]));
    166     checkMonotone(i16ary, 65536);
    167 
    168     // TODO make a template case for the following?
    169 
    170     // do round-trip testing p24 to i16 and float
    171     memcpy_to_p24_from_i16(pary, i16ary, 65536);
    172     memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    173 
    174     // check an intermediate format at a position(???)
    175 #if 0
    176     printf("pary[%d].0 = %u  pary[%d].1 = %u  pary[%d].2 = %u\n",
    177             1025, (unsigned) pary[1025*3],
    178             1025, (unsigned) pary[1025*3+1],
    179             1025, (unsigned) pary[1025*3+2]
    180             );
    181 #endif
    182 
    183     memcpy_to_float_from_p24(fary, pary, 65536);
    184     memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
    185     checkMonotone(fary, 65536);
    186 
    187     memcpy_to_p24_from_float(pary, fary, 65536);
    188     memset(fary, 0, 65536 * sizeof(fary[0]));
    189 
    190     memcpy_to_i16_from_p24(i16ary, pary, 65536);
    191     memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
    192     checkMonotone(i16ary, 65536);
    193 
    194     // do round-trip testing q8_23 to i16 and float
    195     memcpy_to_q8_23_from_i16(i32ary, i16ary, 65536);
    196     memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    197     checkMonotone(i32ary, 65536);
    198 
    199     memcpy_to_float_from_q8_23(fary, i32ary, 65536);
    200     memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    201     checkMonotone(fary, 65536);
    202 
    203     memcpy_to_q8_23_from_float_with_clamp(i32ary, fary, 65536);
    204     memset(fary, 0, 65536 * sizeof(fary[0]));
    205     checkMonotone(i32ary, 65536);
    206 
    207     memcpy_to_i16_from_q8_23(i16ary, i32ary, 65536);
    208     memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    209     checkMonotone(i16ary, 65536);
    210 
    211     // do round-trip testing i32 to i16 and float
    212     memcpy_to_i32_from_i16(i32ary, i16ary, 65536);
    213     memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    214     checkMonotone(i32ary, 65536);
    215 
    216     memcpy_to_float_from_i32(fary, i32ary, 65536);
    217     memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    218     checkMonotone(fary, 65536);
    219 
    220     memcpy_to_i32_from_float(i32ary, fary, 65536);
    221     memset(fary, 0, 65536 * sizeof(fary[0]));
    222     checkMonotone(i32ary, 65536);
    223 
    224     memcpy_to_i16_from_i32(i16ary, i32ary, 65536);
    225     memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    226     checkMonotone(i16ary, 65536);
    227 
    228     // do partial round-trip testing q4_27 to i16 and float
    229     memcpy_to_float_from_i16(fary, i16ary, 65536);
    230     //memset(i16ary, 0, 65536 * sizeof(i16ary[0])); // not cleared: we don't do full roundtrip
    231 
    232     memcpy_to_q4_27_from_float(i32ary, fary, 65536);
    233     memset(fary, 0, 65536 * sizeof(fary[0]));
    234     checkMonotone(i32ary, 65536);
    235 
    236     memcpy_to_float_from_q4_27(fary, i32ary, 65536);
    237     memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    238     checkMonotone(fary, 65536);
    239 
    240     // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
    241     EXPECT_EQ(memcmp(i16ary, i16ref, 65536*sizeof(i16ary[0])), 0);
    242 
    243     delete[] i16ref;
    244     delete[] i16ary;
    245     delete[] i32ary;
    246     delete[] fary;
    247     delete[] pary;
    248 }
    249 
    250 template<typename T>
    251 void checkMonotoneOrZero(const T *ary, size_t size)
    252 {
    253     T least = 0;
    254 
    255     for (size_t i = 1; i < size; ++i) {
    256         if (ary[i]) {
    257             EXPECT_LT(least, ary[i]);
    258             least = ary[i];
    259         }
    260     }
    261 }
    262 
    263 TEST(audio_utils_primitives, memcpy_by_channel_mask) {
    264     uint32_t dst_mask;
    265     uint32_t src_mask;
    266     uint16_t *u16ref = new uint16_t[65536];
    267     uint16_t *u16ary = new uint16_t[65536];
    268 
    269     for (size_t i = 0; i < 65536; ++i) {
    270         u16ref[i] = i;
    271     }
    272 
    273     // Test when src mask is 0.  Everything copied is zero.
    274     src_mask = 0;
    275     dst_mask = 0x8d;
    276     memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
    277     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
    278             65536 / popcount(dst_mask));
    279     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0);
    280 
    281     // Test when dst_mask is 0.  Nothing should be copied.
    282     src_mask = 0;
    283     dst_mask = 0;
    284     memset(u16ary, 0, 65536 * sizeof(u16ref[0]));
    285     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
    286             65536);
    287     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0);
    288 
    289     // Test when masks are the same.  One to one copy.
    290     src_mask = dst_mask = 0x8d;
    291     memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
    292     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
    293     EXPECT_EQ(memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * popcount(dst_mask)), 0);
    294 
    295     // Test with a gap in source:
    296     // Input 3 samples, output 4 samples, one zero inserted.
    297     src_mask = 0x8c;
    298     dst_mask = 0x8d;
    299     memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
    300     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
    301             65536 / popcount(dst_mask));
    302     checkMonotoneOrZero(u16ary, 65536);
    303     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65536), 65536 * 3 / 4 - 1);
    304 
    305     // Test with a gap in destination:
    306     // Input 4 samples, output 3 samples, one deleted
    307     src_mask = 0x8d;
    308     dst_mask = 0x8c;
    309     memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
    310     memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
    311             65536 / popcount(src_mask));
    312     checkMonotone(u16ary, 65536 * 3 / 4);
    313 
    314     delete[] u16ref;
    315     delete[] u16ary;
    316 }
    317 
    318 void memcpy_by_channel_mask2(void *dst, uint32_t dst_mask,
    319         const void *src, uint32_t src_mask, size_t sample_size, size_t count)
    320 {
    321     int8_t idxary[32];
    322     uint32_t src_channels = popcount(src_mask);
    323     uint32_t dst_channels =
    324             memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask);
    325 
    326     memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
    327 }
    328 
    329 // a modified version of the memcpy_by_channel_mask test
    330 // but using 24 bit type and memcpy_by_index_array()
    331 TEST(audio_utils_primitives, memcpy_by_index_array) {
    332     uint32_t dst_mask;
    333     uint32_t src_mask;
    334     typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
    335     uint8x3_t *u24ref = new uint8x3_t[65536];
    336     uint8x3_t *u24ary = new uint8x3_t[65536];
    337     uint16_t *u16ref = new uint16_t[65536];
    338     uint16_t *u16ary = new uint16_t[65536];
    339 
    340     EXPECT_EQ(sizeof(uint8x3_t), 3); // 3 bytes per struct
    341 
    342     // tests prepare_index_array_from_masks()
    343     EXPECT_EQ(memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c), 4);
    344     EXPECT_EQ(memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d), 3);
    345 
    346     for (size_t i = 0; i < 65536; ++i) {
    347         u16ref[i] = i;
    348     }
    349     memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
    350 
    351     // Test when src mask is 0.  Everything copied is zero.
    352     src_mask = 0;
    353     dst_mask = 0x8d;
    354     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
    355     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
    356             65536 / popcount(dst_mask));
    357     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
    358     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0);
    359 
    360     // Test when dst_mask is 0.  Nothing should be copied.
    361     src_mask = 0;
    362     dst_mask = 0;
    363     memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
    364     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
    365             65536);
    366     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
    367     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0);
    368 
    369     // Test when masks are the same.  One to one copy.
    370     src_mask = dst_mask = 0x8d;
    371     memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
    372     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
    373     EXPECT_EQ(memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)), 0);
    374 
    375     // Test with a gap in source:
    376     // Input 3 samples, output 4 samples, one zero inserted.
    377     src_mask = 0x8c;
    378     dst_mask = 0x8d;
    379     memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
    380     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
    381             65536 / popcount(dst_mask));
    382     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
    383     checkMonotoneOrZero(u16ary, 65536);
    384     EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65536), 65536 * 3 / 4 - 1);
    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(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
    391     memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
    392             65536 / popcount(src_mask));
    393     memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
    394     checkMonotone(u16ary, 65536 * 3 / 4);
    395 
    396     delete[] u16ref;
    397     delete[] u16ary;
    398     delete[] u24ref;
    399     delete[] u24ary;
    400 }
    401 
    402 TEST(audio_utils_channels, adjust_channels) {
    403     uint16_t *u16ref = new uint16_t[65536];
    404     uint16_t *u16expand = new uint16_t[65536*2];
    405     uint16_t *u16ary = new uint16_t[65536];
    406 
    407     // reference buffer always increases
    408     for (size_t i = 0; i < 65536; ++i) {
    409         u16ref[i] = i;
    410     }
    411 
    412     // expand channels from stereo to quad.
    413     adjust_channels(u16ref /*in_buff*/, 2 /*in_channels*/,
    414             u16expand /*out_buff*/, 4 /*out_channels*/,
    415             sizeof(u16ref[0]) /*sample_size_in_bytes*/,
    416             sizeof(u16ref[0])*65536 /*num_in_bytes*/);
    417 
    418     // expanded buffer must increase (or be zero)
    419     checkMonotoneOrZero(u16expand, 65536*2);
    420 
    421     // contract channels back to stereo.
    422     adjust_channels(u16expand /*in_buff*/, 4 /*in_channels*/,
    423             u16ary /*out_buff*/, 2 /*out_channels*/,
    424             sizeof(u16expand[0]) /*sample_size_in_bytes*/,
    425             sizeof(u16expand[0])*65536*2 /*num_in_bytes*/);
    426 
    427     // must be identical to original.
    428     EXPECT_EQ(memcmp(u16ary, u16ref, sizeof(u16ref[0])*65536), 0);
    429 
    430     delete[] u16ref;
    431     delete[] u16expand;
    432     delete[] u16ary;
    433 }
    434