TEST(audio_utils_primitives, memcpy) {
    // test round-trip.
    int16_t *i16ref = new int16_t[65536];
    int16_t *i16ary = new int16_t[65536];
    int32_t *i32ary = new int32_t[65536];
    float *fary = new float[65536];
    uint8_t *pary = new uint8_t[65536*3];

    for (size_t i = 0; i < 65536; ++i) {
        i16ref[i] = i16ary[i] = i - 32768;
    }

    // do round-trip testing i16 and float
    memcpy_to_float_from_i16(fary, i16ary, 65536);
    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    checkMonotone(fary, 65536);

    memcpy_to_i16_from_float(i16ary, fary, 65536);
    memset(fary, 0, 65536 * sizeof(fary[0]));
    checkMonotone(i16ary, 65536);

    // TODO make a template case for the following?

    // do round-trip testing p24 to i16 and float
    memcpy_to_p24_from_i16(pary, i16ary, 65536);
    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));

    // check an intermediate format at a position(???)
#if 0
    printf("pary[%d].0 = %u  pary[%d].1 = %u  pary[%d].2 = %u\n",
            1025, (unsigned) pary[1025*3],
            1025, (unsigned) pary[1025*3+1],
            1025, (unsigned) pary[1025*3+2]
            );
#endif

    memcpy_to_float_from_p24(fary, pary, 65536);
    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
    checkMonotone(fary, 65536);

    memcpy_to_p24_from_float(pary, fary, 65536);
    memset(fary, 0, 65536 * sizeof(fary[0]));

    memcpy_to_i16_from_p24(i16ary, pary, 65536);
    memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
    checkMonotone(i16ary, 65536);

    // do round-trip testing q8_23 to i16 and float
    memcpy_to_q8_23_from_i16(i32ary, i16ary, 65536);
    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    checkMonotone(i32ary, 65536);

    memcpy_to_float_from_q8_23(fary, i32ary, 65536);
    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    checkMonotone(fary, 65536);

    memcpy_to_q8_23_from_float_with_clamp(i32ary, fary, 65536);
    memset(fary, 0, 65536 * sizeof(fary[0]));
    checkMonotone(i32ary, 65536);

    memcpy_to_i16_from_q8_23(i16ary, i32ary, 65536);
    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    checkMonotone(i16ary, 65536);

    // do round-trip testing i32 to i16 and float
    memcpy_to_i32_from_i16(i32ary, i16ary, 65536);
    memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
    checkMonotone(i32ary, 65536);

    memcpy_to_float_from_i32(fary, i32ary, 65536);
    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    checkMonotone(fary, 65536);

    memcpy_to_i32_from_float(i32ary, fary, 65536);
    memset(fary, 0, 65536 * sizeof(fary[0]));
    checkMonotone(i32ary, 65536);

    memcpy_to_i16_from_i32(i16ary, i32ary, 65536);
    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    checkMonotone(i16ary, 65536);

    // do partial round-trip testing q4_27 to i16 and float
    memcpy_to_float_from_i16(fary, i16ary, 65536);
    //memset(i16ary, 0, 65536 * sizeof(i16ary[0])); // not cleared: we don't do full roundtrip

    memcpy_to_q4_27_from_float(i32ary, fary, 65536);
    memset(fary, 0, 65536 * sizeof(fary[0]));
    checkMonotone(i32ary, 65536);

    memcpy_to_float_from_q4_27(fary, i32ary, 65536);
    memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
    checkMonotone(fary, 65536);

    // at the end, our i16ary must be the same. (Monotone should be equivalent to this)
    EXPECT_EQ(memcmp(i16ary, i16ref, 65536*sizeof(i16ary[0])), 0);

    delete[] i16ref;
    delete[] i16ary;
    delete[] i32ary;
    delete[] fary;
    delete[] pary;
}
// 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;
}
예제 #3
0
void memcpy_by_audio_format(void *dst, audio_format_t dst_format,
        const void *src, audio_format_t src_format, size_t count)
{
    /* default cases for error falls through to fatal log below. */
    if (dst_format == src_format) {
        switch (dst_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
        case AUDIO_FORMAT_PCM_FLOAT:
        case AUDIO_FORMAT_PCM_8_BIT:
        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
        case AUDIO_FORMAT_PCM_32_BIT:
        case AUDIO_FORMAT_PCM_8_24_BIT:
            memcpy(dst, src, count * audio_bytes_per_sample(dst_format));
            return;
        default:
            break;
        }
    }
    switch (dst_format) {
    case AUDIO_FORMAT_PCM_16_BIT:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_FLOAT:
            memcpy_to_i16_from_float((int16_t*)dst, (float*)src, count);
            return;
        case AUDIO_FORMAT_PCM_8_BIT:
            memcpy_to_i16_from_u8((int16_t*)dst, (uint8_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
            memcpy_to_i16_from_p24((int16_t*)dst, (uint8_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_32_BIT:
            memcpy_to_i16_from_i32((int16_t*)dst, (int32_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_8_24_BIT:
            memcpy_to_i16_from_q8_23((int16_t*)dst, (int32_t*)src, count);
            return;
        default:
            break;
        }
        break;
    case AUDIO_FORMAT_PCM_FLOAT:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
            memcpy_to_float_from_i16((float*)dst, (int16_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_8_BIT:
            memcpy_to_float_from_u8((float*)dst, (uint8_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
            memcpy_to_float_from_p24((float*)dst, (uint8_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_32_BIT:
            memcpy_to_float_from_i32((float*)dst, (int32_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_8_24_BIT:
            memcpy_to_float_from_q8_23((float*)dst, (int32_t*)src, count);
            return;
        default:
            break;
        }
        break;
    case AUDIO_FORMAT_PCM_8_BIT:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
            memcpy_to_u8_from_i16((uint8_t*)dst, (int16_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_FLOAT:
            memcpy_to_u8_from_float((uint8_t*)dst, (float*)src, count);
            return;
        default:
            break;
        }
        break;
    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
            memcpy_to_p24_from_i16((uint8_t*)dst, (int16_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_FLOAT:
            memcpy_to_p24_from_float((uint8_t*)dst, (float*)src, count);
            return;
        default:
            break;
        }
        break;
    case AUDIO_FORMAT_PCM_32_BIT:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
            memcpy_to_i32_from_i16((int32_t*)dst, (int16_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_FLOAT:
            memcpy_to_i32_from_float((int32_t*)dst, (float*)src, count);
            return;
        default:
            break;
        }
        break;
    case AUDIO_FORMAT_PCM_8_24_BIT:
        switch (src_format) {
        case AUDIO_FORMAT_PCM_16_BIT:
            memcpy_to_q8_23_from_i16((int32_t*)dst, (int16_t*)src, count);
            return;
        case AUDIO_FORMAT_PCM_FLOAT:
            memcpy_to_q8_23_from_float_with_clamp((int32_t*)dst, (float*)src, count);
            return;
        case AUDIO_FORMAT_PCM_24_BIT_PACKED: {
            memcpy_to_q8_23_from_p24((int32_t *)dst, (uint8_t *)src, count);
            return;
        }
        default:
            break;
        }
        break;
    default:
        break;
    }
    LOG_ALWAYS_FATAL("invalid src format %#x for dst format %#x",
            src_format, dst_format);
}