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