From: Peter Meerwald <p.meerwald@xxxxxxxxxxxxxxxxxx> add 4-channel remapping tests Signed-off-by: Peter Meerwald <p.meerwald at bct-electronic.com> --- src/tests/cpu-test.c | 304 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 231 insertions(+), 73 deletions(-) diff --git a/src/tests/cpu-test.c b/src/tests/cpu-test.c index 3aa73f2..ea18eef 100644 --- a/src/tests/cpu-test.c +++ b/src/tests/cpu-test.c @@ -273,7 +273,7 @@ static void run_conv_test_float_to_s16( PA_DECLARE_ALIGNED(8, int16_t, s[SAMPLES]) = { 0 }; PA_DECLARE_ALIGNED(8, int16_t, s_ref[SAMPLES]) = { 0 }; - PA_DECLARE_ALIGNED(8, float, f[SAMPLES]); + PA_DECLARE_ALIGNED(8, float, f[SAMPLES]) = { 0 }; int16_t *samples, *samples_ref; float *floats; int i, nsamples; @@ -326,7 +326,7 @@ static void run_conv_test_s16_to_float( PA_DECLARE_ALIGNED(8, float, f[SAMPLES]) = { 0 }; PA_DECLARE_ALIGNED(8, float, f_ref[SAMPLES]) = { 0 }; - PA_DECLARE_ALIGNED(8, int16_t, s[SAMPLES]); + PA_DECLARE_ALIGNED(8, int16_t, s[SAMPLES]) = { 0 }; float *floats, *floats_ref; int16_t *samples; int i, nsamples; @@ -476,38 +476,38 @@ END_TEST #define TIMES 1000 #define TIMES2 100 -static void run_remap_test_mono_stereo_float( +static void run_remap_test_mono_channels_float( pa_remap_t *remap, - pa_do_remap_func_t func, - pa_do_remap_func_t orig_func, - int align, - pa_bool_t correct, - pa_bool_t perf) { + pa_do_remap_func_t func, pa_do_remap_func_t orig_func, + int channels, + int align, pa_bool_t correct, pa_bool_t perf) { - PA_DECLARE_ALIGNED(8, float, s_ref[SAMPLES*2]) = { 0 }; - PA_DECLARE_ALIGNED(8, float, s[SAMPLES*2]) = { 0 }; - PA_DECLARE_ALIGNED(8, float, m[SAMPLES]); - float *stereo, *stereo_ref; + PA_DECLARE_ALIGNED(8, float, out_ref[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, float, out[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, float, in[SAMPLES]) = { 0 }; + float *ch, *ch_ref; float *mono; int i, nsamples; + assert(channels == 2 || channels == 4 || channels == 8); + /* Force sample alignment as requested */ - stereo = s + (8 - align); - stereo_ref = s_ref + (8 - align); - mono = m + (8 - align); + ch = out + (8 - align); + ch_ref = out_ref + (8 - align); + mono = in + (8 - align); nsamples = SAMPLES - (8 - align); for (i = 0; i < nsamples; i++) mono[i] = 2.1f * (rand()/(float) RAND_MAX - 0.5f); if (correct) { - orig_func(remap, stereo_ref, mono, nsamples); - func(remap, stereo, mono, nsamples); + orig_func(remap, ch_ref, mono, nsamples); + func(remap, ch, mono, nsamples); - for (i = 0; i < nsamples * 2; i++) { - if (fabsf(stereo[i] - stereo_ref[i]) > 0.0001) { + for (i = 0; i < nsamples * channels; i++) { + if (fabsf(ch[i] - ch_ref[i]) > 0.0001) { pa_log_debug("Correctness test failed: align=%d", align); - pa_log_debug("%d: %.24f != %.24f (%.24f)\n", i, stereo[i], stereo_ref[i], mono[i]); + pa_log_debug("%d: %.24f != %.24f (%.24f)\n", i, ch[i], ch_ref[i], mono[i]); fail(); } } @@ -517,46 +517,46 @@ static void run_remap_test_mono_stereo_float( pa_log_debug("Testing remap performance with %d sample alignment", align); PA_CPU_TEST_RUN_START("func", TIMES, TIMES2) { - func(remap, stereo, mono, nsamples); + func(remap, ch, mono, nsamples); } PA_CPU_TEST_RUN_STOP PA_CPU_TEST_RUN_START("orig", TIMES, TIMES2) { - orig_func(remap, stereo_ref, mono, nsamples); + orig_func(remap, ch_ref, mono, nsamples); } PA_CPU_TEST_RUN_STOP } } -static void run_remap_test_mono_stereo_s16( +static void run_remap_test_mono_channels_s16( pa_remap_t *remap, - pa_do_remap_func_t func, - pa_do_remap_func_t orig_func, - int align, - pa_bool_t correct, - pa_bool_t perf) { + pa_do_remap_func_t func, pa_do_remap_func_t orig_func, + int channels, + int align, pa_bool_t correct, pa_bool_t perf) { - PA_DECLARE_ALIGNED(8, int16_t, s_ref[SAMPLES*2]) = { 0 }; - PA_DECLARE_ALIGNED(8, int16_t, s[SAMPLES*2]) = { 0 }; - PA_DECLARE_ALIGNED(8, int16_t, m[SAMPLES]); - int16_t *stereo, *stereo_ref; + PA_DECLARE_ALIGNED(8, int16_t, out_ref[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, int16_t, out[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, int16_t, in[SAMPLES]) = { 0 }; + int16_t *ch, *ch_ref; int16_t *mono; int i, nsamples; + assert(channels == 2 || channels == 4 || channels == 8); + /* Force sample alignment as requested */ - stereo = s + (8 - align); - stereo_ref = s_ref + (8 - align); - mono = m + (8 - align); + ch = out + (8 - align); + ch_ref = out_ref + (8 - align); + mono = in + (8 - align); nsamples = SAMPLES - (8 - align); pa_random(mono, nsamples * sizeof(int16_t)); if (correct) { - orig_func(remap, stereo_ref, mono, nsamples); - func(remap, stereo, mono, nsamples); + orig_func(remap, ch_ref, mono, nsamples); + func(remap, ch, mono, nsamples); - for (i = 0; i < nsamples * 2; i++) { - if (abs(stereo[i] - stereo_ref[i]) > 1) { + for (i = 0; i < nsamples * channels; i++) { + if (abs(ch[i] - ch_ref[i]) > 1) { pa_log_debug("Correctness test failed: align=%d", align); - pa_log_debug("%d: %d != %d (%d)\n", i, stereo[i], stereo_ref[i], mono[i]); + pa_log_debug("%d: %d != %d (%d)\n", i, ch[i], ch_ref[i], mono[i]); fail(); } } @@ -566,34 +566,35 @@ static void run_remap_test_mono_stereo_s16( pa_log_debug("Testing remap performance with %d sample alignment", align); PA_CPU_TEST_RUN_START("func", TIMES, TIMES2) { - func(remap, stereo, mono, nsamples); + func(remap, ch, mono, nsamples); } PA_CPU_TEST_RUN_STOP PA_CPU_TEST_RUN_START("orig", TIMES, TIMES2) { - orig_func(remap, stereo_ref, mono, nsamples); + orig_func(remap, ch_ref, mono, nsamples); } PA_CPU_TEST_RUN_STOP } } -static void remap_test_mono_stereo_float( - pa_init_remap_func_t init_func, - pa_init_remap_func_t orig_init_func) { +static void remap_test_mono_channels( + pa_init_remap_func_t init_func, pa_init_remap_func_t orig_init_func, + pa_sample_format_t format, int channels) { pa_sample_format_t sf; pa_remap_t remap; pa_sample_spec iss, oss; pa_do_remap_func_t orig_func, func; + int i; - iss.format = oss.format = sf = PA_SAMPLE_FLOAT32NE; + iss.format = oss.format = sf = format; iss.channels = 1; - oss.channels = 2; + oss.channels = channels; remap.format = &sf; remap.i_ss = &iss; remap.o_ss = &oss; - remap.map_table_f[0][0] = 1.0; - remap.map_table_f[1][0] = 1.0; - remap.map_table_i[0][0] = 0x10000; - remap.map_table_i[1][0] = 0x10000; + for (i = 0; i < channels; i++) { + remap.map_table_f[i][0] = 1.0f; + remap.map_table_i[i][0] = PA_VOLUME_NORM; + } orig_init_func(&remap); orig_func = remap.do_remap; if (!orig_func) { @@ -608,31 +609,136 @@ static void remap_test_mono_stereo_float( return; } - run_remap_test_mono_stereo_float(&remap, func, orig_func, 0, TRUE, FALSE); - run_remap_test_mono_stereo_float(&remap, func, orig_func, 1, TRUE, FALSE); - run_remap_test_mono_stereo_float(&remap, func, orig_func, 2, TRUE, FALSE); - run_remap_test_mono_stereo_float(&remap, func, orig_func, 3, TRUE, TRUE); + if (format == PA_SAMPLE_FLOAT32NE) { + run_remap_test_mono_channels_float(&remap, func, orig_func, channels, 0, TRUE, FALSE); + run_remap_test_mono_channels_float(&remap, func, orig_func, channels, 1, TRUE, FALSE); + run_remap_test_mono_channels_float(&remap, func, orig_func, channels, 2, TRUE, FALSE); + run_remap_test_mono_channels_float(&remap, func, orig_func, channels, 3, TRUE, TRUE); + } else if (format == PA_SAMPLE_S16NE) { + run_remap_test_mono_channels_s16(&remap, func, orig_func, channels, 0, TRUE, FALSE); + run_remap_test_mono_channels_s16(&remap, func, orig_func, channels, 1, TRUE, FALSE); + run_remap_test_mono_channels_s16(&remap, func, orig_func, channels, 2, TRUE, FALSE); + run_remap_test_mono_channels_s16(&remap, func, orig_func, channels, 3, TRUE, TRUE); + } else pa_assert_not_reached(); } -static void remap_test_mono_stereo_s16( - pa_init_remap_func_t init_func, - pa_init_remap_func_t orig_init_func) { +static void run_remap_test_channels_mono_float( + pa_remap_t *remap, + pa_do_remap_func_t func, pa_do_remap_func_t orig_func, + int channels, int align, pa_bool_t correct, pa_bool_t perf) { + + PA_DECLARE_ALIGNED(8, float, in[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, float, out[SAMPLES]) = { 0 }; + PA_DECLARE_ALIGNED(8, float, out_ref[SAMPLES]) = { 0 }; + float *ch; + float *mono, *mono_ref; + int i, nsamples; + + assert(channels == 2 || channels == 4 || channels == 8); + + /* Force sample alignment as requested */ + ch = in + (8 - align); + mono_ref = out_ref + (8 - align); + mono = out + (8 - align); + nsamples = SAMPLES - (8 - align); + + for (i = 0; i < nsamples * channels; i++) + ch[i] = 2.1f * (rand()/(float) RAND_MAX - 0.5f); + + if (correct) { + orig_func(remap, mono_ref, ch, nsamples); + func(remap, mono, ch, nsamples); + + for (i = 0; i < nsamples; i++) { + if (fabsf(mono[i] - mono_ref[i]) > 0.0001) { + pa_log_debug("Correctness test failed: align=%d", align); + pa_log_debug("%d: %.24f != %.24f\n", i, mono[i], mono_ref[i]); + fail(); + } + } + } + + if (perf) { + pa_log_debug("Testing remap performance with %d sample alignment", align); + + PA_CPU_TEST_RUN_START("func", TIMES, TIMES2) { + func(remap, mono, ch, nsamples); + } PA_CPU_TEST_RUN_STOP + + PA_CPU_TEST_RUN_START("orig", TIMES, TIMES2) { + orig_func(remap, mono_ref, ch, nsamples); + } PA_CPU_TEST_RUN_STOP + } +} + +static void run_remap_test_channels_mono_s16( + pa_remap_t *remap, + pa_do_remap_func_t func, pa_do_remap_func_t orig_func, + int channels, int align, pa_bool_t correct, pa_bool_t perf) { + + PA_DECLARE_ALIGNED(8, int16_t, in[SAMPLES*8]) = { 0 }; + PA_DECLARE_ALIGNED(8, int16_t, out[SAMPLES]) = { 0 }; + PA_DECLARE_ALIGNED(8, int16_t, out_ref[SAMPLES]) = { 0 }; + int16_t *ch; + int16_t *mono, *mono_ref; + int i, nsamples; + + assert(channels == 2 || channels == 4 || channels == 8); + + /* Force sample alignment as requested */ + ch = in + (8 - align); + mono_ref = out_ref + (8 - align); + mono = out + (8 - align); + nsamples = SAMPLES - (8 - align); + + pa_random(ch, nsamples * channels * sizeof(int16_t)); + + if (correct) { + orig_func(remap, mono_ref, ch, nsamples); + func(remap, mono, ch, nsamples); + + for (i = 0; i < nsamples; i++) { + if (abs(mono[i] - mono_ref[i]) > 1) { + pa_log_debug("Correctness test failed: align=%d", align); + pa_log_debug("%d: %hx != %hx\n", i, mono[i], mono_ref[i]); + fail(); + } + } + } + + if (perf) { + pa_log_debug("Testing remap performance with %d sample alignment", align); + + PA_CPU_TEST_RUN_START("func", TIMES, TIMES2) { + func(remap, mono, ch, nsamples); + } PA_CPU_TEST_RUN_STOP + + PA_CPU_TEST_RUN_START("orig", TIMES, TIMES2) { + orig_func(remap, mono_ref, ch, nsamples); + } PA_CPU_TEST_RUN_STOP + } +} + +static void remap_test_channels_mono( + pa_init_remap_func_t init_func, pa_init_remap_func_t orig_init_func, + pa_sample_format_t format, int channels) { pa_sample_format_t sf; pa_remap_t remap; pa_sample_spec iss, oss; pa_do_remap_func_t orig_func, func; + int i; - iss.format = oss.format = sf = PA_SAMPLE_S16NE; - iss.channels = 1; - oss.channels = 2; + iss.format = oss.format = sf = format; + iss.channels = channels; + oss.channels = 1; remap.format = &sf; remap.i_ss = &iss; remap.o_ss = &oss; - remap.map_table_f[0][0] = 1.0; - remap.map_table_f[1][0] = 1.0; - remap.map_table_i[0][0] = 0x10000; - remap.map_table_i[1][0] = 0x10000; + for (i = 0; i < channels; i++) { + remap.map_table_f[0][i] = 1.0f / channels; + remap.map_table_i[0][i] = PA_VOLUME_NORM / channels; + } orig_init_func(&remap); orig_func = remap.do_remap; if (!orig_func) { @@ -647,10 +753,17 @@ static void remap_test_mono_stereo_s16( return; } - run_remap_test_mono_stereo_s16(&remap, func, orig_func, 0, TRUE, FALSE); - run_remap_test_mono_stereo_s16(&remap, func, orig_func, 1, TRUE, FALSE); - run_remap_test_mono_stereo_s16(&remap, func, orig_func, 2, TRUE, FALSE); - run_remap_test_mono_stereo_s16(&remap, func, orig_func, 3, TRUE, TRUE); + if (format == PA_SAMPLE_FLOAT32NE) { + run_remap_test_channels_mono_float(&remap, func, orig_func, channels, 0, TRUE, FALSE); + run_remap_test_channels_mono_float(&remap, func, orig_func, channels, 1, TRUE, FALSE); + run_remap_test_channels_mono_float(&remap, func, orig_func, channels, 2, TRUE, FALSE); + run_remap_test_channels_mono_float(&remap, func, orig_func, channels, 3, TRUE, TRUE); + } else if (format == PA_SAMPLE_S16NE) { + run_remap_test_channels_mono_s16(&remap, func, orig_func, channels, 0, TRUE, FALSE); + run_remap_test_channels_mono_s16(&remap, func, orig_func, channels, 1, TRUE, FALSE); + run_remap_test_channels_mono_s16(&remap, func, orig_func, channels, 2, TRUE, FALSE); + run_remap_test_channels_mono_s16(&remap, func, orig_func, channels, 3, TRUE, TRUE); + } else pa_assert_not_reached(); } #if defined (__i386__) || defined (__amd64__) @@ -668,10 +781,10 @@ START_TEST (remap_mmx_test) { orig_init_func = pa_get_init_remap_func(); pa_remap_func_init_mmx(flags); init_func = pa_get_init_remap_func(); - remap_test_mono_stereo_float(init_func, orig_init_func); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 2); pa_log_debug("Checking MMX remap (s16, mono->stereo)"); - remap_test_mono_stereo_s16(init_func, orig_init_func); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_S16NE, 2); } END_TEST @@ -689,14 +802,54 @@ START_TEST (remap_sse2_test) { orig_init_func = pa_get_init_remap_func(); pa_remap_func_init_sse(flags); init_func = pa_get_init_remap_func(); - remap_test_mono_stereo_float(init_func, orig_init_func); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 2); pa_log_debug("Checking SSE2 remap (s16, mono->stereo)"); - remap_test_mono_stereo_s16(init_func, orig_init_func); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_S16NE, 2); } END_TEST #endif /* defined (__i386__) || defined (__amd64__) */ +#if defined (__arm__) && defined (__linux__) +#ifdef HAVE_NEON +START_TEST (remap_neon_test) { + pa_cpu_arm_flag_t flags = 0; + pa_init_remap_func_t init_func, orig_init_func; + + pa_cpu_get_arm_flags(&flags); + if (!(flags & PA_CPU_ARM_NEON)) { + pa_log_info("NEON not supported. Skipping"); + return; + } + + pa_log_debug("Checking NEON remap (float, mono->stereo)"); + orig_init_func = pa_get_init_remap_func(); + pa_remap_func_init_neon(flags); + init_func = pa_get_init_remap_func(); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 2); + + pa_log_debug("Checking NEON remap (float, mono->ch4)"); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 4); + + pa_log_debug("Checking NEON remap (s16, mono->stereo)"); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_S16NE, 2); + pa_log_debug("Checking NEON remap (s16, mono->ch4)"); + remap_test_mono_channels(init_func, orig_init_func, PA_SAMPLE_S16NE, 4); + + pa_log_debug("Checking NEON remap (float, stereo->mono)"); + remap_test_channels_mono(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 2); + pa_log_debug("Checking NEON remap (float, ch4->mono)"); + remap_test_channels_mono(init_func, orig_init_func, PA_SAMPLE_FLOAT32NE, 4); + + pa_log_debug("Checking NEON remap (s16, stereo->mono)"); + remap_test_channels_mono(init_func, orig_init_func, PA_SAMPLE_S16NE, 2); + pa_log_debug("Checking NEON remap (s16, ch4->mono)"); + remap_test_channels_mono(init_func, orig_init_func, PA_SAMPLE_S16NE, 4); +} +END_TEST +#endif +#endif + #undef SAMPLES #undef TIMES #undef TIMES2 @@ -896,6 +1049,11 @@ int main(int argc, char *argv[]) { tcase_add_test(tc, remap_mmx_test); tcase_add_test(tc, remap_sse2_test); #endif +#if defined (__arm__) && defined (__linux__) +#if HAVE_NEON + tcase_add_test(tc, remap_neon_test); +#endif +#endif tcase_set_timeout(tc, 120); suite_add_tcase(s, tc); /* Mix tests */ -- 1.7.9.5