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