[pulseaudio-discuss] [PATCH 09/10] cpu-test: Add test cases for remap, remap_neon

Peter Meerwald pmeerw at pmeerw.net
Fri Mar 29 08:56:50 PDT 2013


From: Peter Meerwald <p.meerwald at bct-electronic.com>

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



More information about the pulseaudio-discuss mailing list