void memcpy_by_channel_mask2(void *dst, uint32_t dst_mask, const void *src, uint32_t src_mask, size_t sample_size, size_t count) { int8_t idxary[32]; uint32_t src_channels = popcount(src_mask); uint32_t dst_channels = memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask); memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count); }
size_t memcpy_by_index_array_initialization_from_channel_mask(int8_t *idxary, size_t arysize, audio_channel_mask_t dst_channel_mask, audio_channel_mask_t src_channel_mask) { const audio_channel_representation_t src_representation = audio_channel_mask_get_representation(src_channel_mask); const audio_channel_representation_t dst_representation = audio_channel_mask_get_representation(dst_channel_mask); const uint32_t src_bits = audio_channel_mask_get_bits(src_channel_mask); const uint32_t dst_bits = audio_channel_mask_get_bits(dst_channel_mask); switch (src_representation) { case AUDIO_CHANNEL_REPRESENTATION_POSITION: switch (dst_representation) { case AUDIO_CHANNEL_REPRESENTATION_POSITION: return memcpy_by_index_array_initialization(idxary, arysize, dst_bits, src_bits); case AUDIO_CHANNEL_REPRESENTATION_INDEX: return memcpy_by_index_array_initialization_dst_index(idxary, arysize, dst_bits, src_bits); default: return 0; } break; case AUDIO_CHANNEL_REPRESENTATION_INDEX: switch (dst_representation) { case AUDIO_CHANNEL_REPRESENTATION_POSITION: return memcpy_by_index_array_initialization_src_index(idxary, arysize, dst_bits, src_bits); case AUDIO_CHANNEL_REPRESENTATION_INDEX: return memcpy_by_index_array_initialization(idxary, arysize, dst_bits, src_bits); default: return 0; } break; default: return 0; } }
void memcpy_by_channel_mask(void *dst, uint32_t dst_mask, const void *src, uint32_t src_mask, size_t sample_size, size_t count) { #if 0 /* alternate way of handling memcpy_by_channel_mask by using the idxary */ int8_t idxary[32]; uint32_t src_channels = popcount(src_mask); uint32_t dst_channels = memcpy_by_index_array_initialization(idxary, 32, dst_mask, src_mask); memcpy_by_idxary(dst, dst_channels, src, src_channels, idxary, sample_size, count); #else if (dst_mask == src_mask) { memcpy(dst, src, sample_size * popcount(dst_mask) * count); return; } switch (sample_size) { case 1: { uint8_t *udst = (uint8_t*)dst; const uint8_t *usrc = (const uint8_t*)src; copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); } break; case 2: { uint16_t *udst = (uint16_t*)dst; const uint16_t *usrc = (const uint16_t*)src; copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); } break; case 3: { /* could be slow. use a struct to represent 3 bytes of data. */ uint8x3_t *udst = (uint8x3_t*)dst; const uint8x3_t *usrc = (const uint8x3_t*)src; static const uint8x3_t zero; /* tricky - we use this to zero out a sample */ copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, zero); } break; case 4: { uint32_t *udst = (uint32_t*)dst; const uint32_t *usrc = (const uint32_t*)src; copy_frame_by_mask(udst, dst_mask, usrc, src_mask, count, 0); } break; default: abort(); /* illegal value */ break; } #endif }
// a modified version of the memcpy_by_channel_mask test // but using 24 bit type and memcpy_by_index_array() TEST(audio_utils_primitives, memcpy_by_index_array) { uint32_t dst_mask; uint32_t src_mask; typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t; uint8x3_t *u24ref = new uint8x3_t[65536]; uint8x3_t *u24ary = new uint8x3_t[65536]; uint16_t *u16ref = new uint16_t[65536]; uint16_t *u16ary = new uint16_t[65536]; EXPECT_EQ(sizeof(uint8x3_t), 3); // 3 bytes per struct // tests prepare_index_array_from_masks() EXPECT_EQ(memcpy_by_index_array_initialization(NULL, 0, 0x8d, 0x8c), 4); EXPECT_EQ(memcpy_by_index_array_initialization(NULL, 0, 0x8c, 0x8d), 3); for (size_t i = 0; i < 65536; ++i) { u16ref[i] = i; } memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536); // Test when src mask is 0. Everything copied is zero. src_mask = 0; dst_mask = 0x8d; memset(u24ary, 0x99, 65536 * sizeof(u24ary[0])); memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 65536 / popcount(dst_mask)); memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536); EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0); // Test when dst_mask is 0. Nothing should be copied. src_mask = 0; dst_mask = 0; memset(u24ary, 0, 65536 * sizeof(u24ary[0])); memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 65536); memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536); EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65530), 0); // Test when masks are the same. One to one copy. src_mask = dst_mask = 0x8d; memset(u24ary, 0x99, 65536 * sizeof(u24ary[0])); memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555); EXPECT_EQ(memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)), 0); // Test with a gap in source: // Input 3 samples, output 4 samples, one zero inserted. src_mask = 0x8c; dst_mask = 0x8d; memset(u24ary, 0x9, 65536 * sizeof(u24ary[0])); memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 65536 / popcount(dst_mask)); memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536); checkMonotoneOrZero(u16ary, 65536); EXPECT_EQ(nonZeroMono16((int16_t*)u16ary, 65536), 65536 * 3 / 4 - 1); // Test with a gap in destination: // Input 4 samples, output 3 samples, one deleted src_mask = 0x8d; dst_mask = 0x8c; memset(u24ary, 0x9, 65536 * sizeof(u24ary[0])); memcpy_by_channel_mask2(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 65536 / popcount(src_mask)); memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536); checkMonotone(u16ary, 65536 * 3 / 4); delete[] u16ref; delete[] u16ary; delete[] u24ref; delete[] u24ary; }