]> code.delx.au - pulseaudio/blobdiff - src/tests/resampler-test.c
Remove unnecessary #includes
[pulseaudio] / src / tests / resampler-test.c
index 6959127b5a032b527dd9e55ae496d5bb780c26b9..78461da57c72324483d369a79386f888a90eac12 100644 (file)
@@ -3,7 +3,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #endif
 
 #include <stdio.h>
+#include <getopt.h>
+#include <locale.h>
 
+#include <pulse/i18n.h>
+#include <pulse/pulseaudio.h>
+
+#include <pulse/rtclock.h>
 #include <pulse/sample.h>
 #include <pulse/volume.h>
 
 #include <pulsecore/endianmacros.h>
 #include <pulsecore/memblock.h>
 #include <pulsecore/sample-util.h>
-
-#include <liboil/liboil.h>
-
-static float swap_float(float a) {
-    uint32_t *b = (uint32_t*) &a;
-    *b = PA_UINT32_SWAP(*b);
-    return a;
-}
+#include <pulsecore/core-util.h>
 
 static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
     void *d;
@@ -54,7 +53,7 @@ static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
             uint8_t *u = d;
 
             for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
-                printf("0x%02x ", *(u++));
+                printf("      0x%02x ", *(u++));
 
             break;
         }
@@ -64,7 +63,7 @@ static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
             uint16_t *u = d;
 
             for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
-                printf("0x%04x ", *(u++));
+                printf("    0x%04x ", *(u++));
 
             break;
         }
@@ -79,18 +78,40 @@ static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) {
             break;
         }
 
+        case PA_SAMPLE_S24_32NE:
+        case PA_SAMPLE_S24_32RE: {
+            uint32_t *u = d;
+
+            for (i = 0; i < chunk->length / pa_frame_size(ss); i++)
+                printf("0x%08x ", *(u++));
+
+            break;
+        }
+
         case PA_SAMPLE_FLOAT32NE:
         case PA_SAMPLE_FLOAT32RE: {
             float *u = d;
 
             for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
-                printf("%1.3g ",  ss->format == PA_SAMPLE_FLOAT32NE ? *u : swap_float(*u));
+                printf("%4.3g ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u));
                 u++;
             }
 
             break;
         }
 
+        case PA_SAMPLE_S24LE:
+        case PA_SAMPLE_S24BE: {
+            uint8_t *u = d;
+
+            for (i = 0; i < chunk->length / pa_frame_size(ss); i++) {
+                printf("  0x%06x ", PA_READ24NE(u));
+                u += pa_frame_size(ss);
+            }
+
+            break;
+        }
+
         default:
             pa_assert_not_reached();
     }
@@ -162,6 +183,23 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
             break;
         }
 
+        case PA_SAMPLE_S24_32NE:
+        case PA_SAMPLE_S24_32RE: {
+            uint32_t *u = d;
+
+            u[0] = 0x000001;
+            u[1] = 0xFF0002;
+            u[2] = 0x7F0003;
+            u[3] = 0x800004;
+            u[4] = 0x9f0005;
+            u[5] = 0x3f0006;
+            u[6] =    0x107;
+            u[7] = 0xF00008;
+            u[8] =   0x2009;
+            u[9] =   0x210A;
+            break;
+        }
+
         case PA_SAMPLE_FLOAT32NE:
         case PA_SAMPLE_FLOAT32RE: {
             float *u = d;
@@ -179,11 +217,28 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
 
             if (ss->format == PA_SAMPLE_FLOAT32RE)
                 for (i = 0; i < 10; i++)
-                    u[i] = swap_float(u[i]);
+                    u[i] = PA_FLOAT32_SWAP(u[i]);
 
             break;
         }
 
+        case PA_SAMPLE_S24NE:
+        case PA_SAMPLE_S24RE: {
+            uint8_t *u = d;
+
+            PA_WRITE24NE(u,    0x000001);
+            PA_WRITE24NE(u+3,  0xFF0002);
+            PA_WRITE24NE(u+6,  0x7F0003);
+            PA_WRITE24NE(u+9,  0x800004);
+            PA_WRITE24NE(u+12, 0x9f0005);
+            PA_WRITE24NE(u+15, 0x3f0006);
+            PA_WRITE24NE(u+18,    0x107);
+            PA_WRITE24NE(u+21, 0xF00008);
+            PA_WRITE24NE(u+24,   0x2009);
+            PA_WRITE24NE(u+27,   0x210A);
+            break;
+        }
+
         default:
             pa_assert_not_reached();
     }
@@ -193,35 +248,209 @@ static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) {
     return r;
 }
 
+static void help(const char *argv0) {
+    printf(_("%s [options]\n\n"
+             "-h, --help                            Show this help\n"
+             "-v, --verbose                         Print debug messages\n"
+             "      --from-rate=SAMPLERATE          From sample rate in Hz (defaults to 44100)\n"
+             "      --from-format=SAMPLEFORMAT      From sample type (defaults to s16le)\n"
+             "      --from-channels=CHANNELS        From number of channels (defaults to 1)\n"
+             "      --to-rate=SAMPLERATE            To sample rate in Hz (defaults to 44100)\n"
+             "      --to-format=SAMPLEFORMAT        To sample type (defaults to s16le)\n"
+             "      --to-channels=CHANNELS          To number of channels (defaults to 1)\n"
+             "      --resample-method=METHOD        Resample method (defaults to auto)\n"
+             "      --seconds=SECONDS               From stream duration (defaults to 60)\n"
+             "\n"
+             "If the formats are not specified, the test performs all formats combinations,\n"
+             "back and forth.\n"
+             "\n"
+             "Sample type must be one of s16le, s16be, u8, float32le, float32be, ulaw, alaw,\n"
+             "32le, s32be (defaults to s16ne)\n"
+             "\n"
+             "See --dump-resample-methods for possible values of resample methods.\n"),
+             argv0);
+}
+
+enum {
+    ARG_VERSION = 256,
+    ARG_FROM_SAMPLERATE,
+    ARG_FROM_SAMPLEFORMAT,
+    ARG_FROM_CHANNELS,
+    ARG_TO_SAMPLERATE,
+    ARG_TO_SAMPLEFORMAT,
+    ARG_TO_CHANNELS,
+    ARG_SECONDS,
+    ARG_RESAMPLE_METHOD,
+    ARG_DUMP_RESAMPLE_METHODS
+};
+
+static void dump_resample_methods(void) {
+    int i;
+
+    for (i = 0; i < PA_RESAMPLER_MAX; i++)
+        if (pa_resample_method_supported(i))
+            printf("%s\n", pa_resample_method_to_string(i));
+
+}
+
 int main(int argc, char *argv[]) {
-    pa_mempool *pool;
+    pa_mempool *pool = NULL;
     pa_sample_spec a, b;
     pa_cvolume v;
-
-    oil_init();
-    pa_log_set_maximal_level(PA_LOG_DEBUG);
-
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    int ret = 1, verbose = 0, c;
+    pa_bool_t all_formats = TRUE;
+    pa_resample_method_t method;
+    int seconds;
+
+    static const struct option long_options[] = {
+        {"help",                  0, NULL, 'h'},
+        {"verbose",               0, NULL, 'v'},
+        {"version",               0, NULL, ARG_VERSION},
+        {"from-rate",             1, NULL, ARG_FROM_SAMPLERATE},
+        {"from-format",           1, NULL, ARG_FROM_SAMPLEFORMAT},
+        {"from-channels",         1, NULL, ARG_FROM_CHANNELS},
+        {"to-rate",               1, NULL, ARG_TO_SAMPLERATE},
+        {"to-format",             1, NULL, ARG_TO_SAMPLEFORMAT},
+        {"to-channels",           1, NULL, ARG_TO_CHANNELS},
+        {"seconds",               1, NULL, ARG_SECONDS},
+        {"resample-method",       1, NULL, ARG_RESAMPLE_METHOD},
+        {"dump-resample-methods", 0, NULL, ARG_DUMP_RESAMPLE_METHODS},
+        {NULL,                    0, NULL, 0}
+    };
+
+    setlocale(LC_ALL, "");
+    bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
+
+    pa_log_set_level(PA_LOG_DEBUG);
+
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     a.channels = b.channels = 1;
     a.rate = b.rate = 44100;
-
+    a.format = b.format = PA_SAMPLE_S16LE;
     v.channels = a.channels;
     v.values[0] = pa_sw_volume_from_linear(0.5);
 
+    method = PA_RESAMPLER_AUTO;
+    seconds = 60;
+
+    while ((c = getopt_long(argc, argv, "hv", long_options, NULL)) != -1) {
+
+        switch (c) {
+            case 'h' :
+                help(argv[0]);
+                ret = 0;
+                goto quit;
+
+            case 'v':
+                pa_log_set_level(PA_LOG_DEBUG);
+                verbose = 1;
+                break;
+
+            case ARG_VERSION:
+                printf(_("%s %s\n"), argv[0], PACKAGE_VERSION);
+                ret = 0;
+                goto quit;
+
+            case ARG_DUMP_RESAMPLE_METHODS:
+                dump_resample_methods();
+                ret = 0;
+                goto quit;
+
+            case ARG_FROM_CHANNELS:
+                a.channels = (uint8_t) atoi(optarg);
+                break;
+
+            case ARG_FROM_SAMPLEFORMAT:
+                a.format = pa_parse_sample_format(optarg);
+                all_formats = FALSE;
+                break;
+
+            case ARG_FROM_SAMPLERATE:
+                a.rate = (uint32_t) atoi(optarg);
+                break;
+
+            case ARG_TO_CHANNELS:
+                b.channels = (uint8_t) atoi(optarg);
+                break;
+
+            case ARG_TO_SAMPLEFORMAT:
+                b.format = pa_parse_sample_format(optarg);
+                all_formats = FALSE;
+                break;
+
+            case ARG_TO_SAMPLERATE:
+                b.rate = (uint32_t) atoi(optarg);
+                break;
+
+            case ARG_SECONDS:
+                seconds = atoi(optarg);
+                break;
+
+            case ARG_RESAMPLE_METHOD:
+                if (*optarg == '\0' || pa_streq(optarg, "help")) {
+                    dump_resample_methods();
+                    ret = 0;
+                    goto quit;
+                }
+                method = pa_parse_resample_method(optarg);
+                break;
+
+            default:
+                goto quit;
+        }
+    }
+
+    ret = 0;
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
+
+    if (!all_formats) {
+
+        pa_resampler *resampler;
+        pa_memchunk i, j;
+        pa_usec_t ts;
+
+        if (verbose) {
+            printf(_("Compilation CFLAGS: %s\n"), PA_CFLAGS);
+            printf(_("=== %d seconds: %d Hz %d ch (%s) -> %d Hz %d ch (%s)\n"), seconds,
+                   a.rate, a.channels, pa_sample_format_to_string(a.format),
+                   b.rate, b.channels, pa_sample_format_to_string(b.format));
+        }
+
+        ts = pa_rtclock_now();
+        pa_assert_se(resampler = pa_resampler_new(pool, &a, NULL, &b, NULL, method, 0));
+        printf("init: %llu\n", (long long unsigned)(pa_rtclock_now() - ts));
+
+        i.memblock = pa_memblock_new(pool, pa_usec_to_bytes(1*PA_USEC_PER_SEC, &a) / pa_frame_size(&a));
+
+        ts = pa_rtclock_now();
+        i.length = pa_memblock_get_length(i.memblock);
+        i.index = 0;
+        while (seconds--) {
+            pa_resampler_run(resampler, &i, &j);
+            pa_memblock_unref(j.memblock);
+        }
+        printf("resampling: %llu\n", (long long unsigned)(pa_rtclock_now() - ts));
+        pa_memblock_unref(i.memblock);
+
+        pa_resampler_free(resampler);
+
+        goto quit;
+    }
+
     for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
         for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
-
             pa_resampler *forth, *back;
             pa_memchunk i, j, k;
 
-            printf("=== %s -> %s -> %s -> /2\n",
-                   pa_sample_format_to_string(a.format),
-                   pa_sample_format_to_string(b.format),
-                   pa_sample_format_to_string(a.format));
+            if (verbose)
+                printf("=== %s -> %s -> %s -> /2\n",
+                       pa_sample_format_to_string(a.format),
+                       pa_sample_format_to_string(b.format),
+                       pa_sample_format_to_string(a.format));
 
-            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, 0));
-            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, 0));
+            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, method, 0));
+            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, method, 0));
 
             i.memblock = generate_block(pool, &a);
             i.length = pa_memblock_get_length(i.memblock);
@@ -229,14 +458,18 @@ int main(int argc, char *argv[]) {
             pa_resampler_run(forth, &i, &j);
             pa_resampler_run(back, &j, &k);
 
+            printf("before:  ");
             dump_block(&a, &i);
+            printf("after :  ");
             dump_block(&b, &j);
+            printf("reverse: ");
             dump_block(&a, &k);
 
             pa_memblock_unref(j.memblock);
             pa_memblock_unref(k.memblock);
 
             pa_volume_memchunk(&i, &a, &v);
+            printf("volume:  ");
             dump_block(&a, &i);
 
             pa_memblock_unref(i.memblock);
@@ -246,7 +479,9 @@ int main(int argc, char *argv[]) {
         }
     }
 
-    pa_mempool_free(pool);
+ quit:
+    if (pool)
+        pa_mempool_free(pool);
 
-    return 0;
+    return ret;
 }