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 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 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 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> 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 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 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 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> 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 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 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() 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 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() 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 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() 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 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