2 This file is part of PulseAudio.
4 PulseAudio is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published
6 by the Free Software Foundation; either version 2.1 of the License,
7 or (at your option) any later version.
9 PulseAudio is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with PulseAudio; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 #include <pulse/pulseaudio.h>
30 #include <pulse/rtclock.h>
31 #include <pulse/sample.h>
32 #include <pulse/volume.h>
34 #include <pulsecore/i18n.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/resampler.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/endianmacros.h>
39 #include <pulsecore/memblock.h>
40 #include <pulsecore/sample-util.h>
41 #include <pulsecore/core-util.h>
43 static void dump_block(const char *label
, const pa_sample_spec
*ss
, const pa_memchunk
*chunk
) {
47 if (getenv("MAKE_CHECK"))
49 printf("%s: \t", label
);
51 d
= pa_memblock_acquire(chunk
->memblock
);
57 case PA_SAMPLE_ALAW
: {
60 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++)
61 printf(" 0x%02x ", *(u
++));
67 case PA_SAMPLE_S16RE
: {
70 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++)
71 printf(" 0x%04x ", *(u
++));
77 case PA_SAMPLE_S32RE
: {
80 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++)
81 printf("0x%08x ", *(u
++));
86 case PA_SAMPLE_S24_32NE
:
87 case PA_SAMPLE_S24_32RE
: {
90 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++)
91 printf("0x%08x ", *(u
++));
96 case PA_SAMPLE_FLOAT32NE
:
97 case PA_SAMPLE_FLOAT32RE
: {
100 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++) {
101 printf("%4.3g ", ss
->format
== PA_SAMPLE_FLOAT32NE
? *u
: PA_FLOAT32_SWAP(*u
));
108 case PA_SAMPLE_S24LE
:
109 case PA_SAMPLE_S24BE
: {
112 for (i
= 0; i
< chunk
->length
/ pa_frame_size(ss
); i
++) {
113 printf(" 0x%06x ", PA_READ24NE(u
));
114 u
+= pa_frame_size(ss
);
121 pa_assert_not_reached();
126 pa_memblock_release(chunk
->memblock
);
129 static pa_memblock
* generate_block(pa_mempool
*pool
, const pa_sample_spec
*ss
) {
134 pa_assert_se(r
= pa_memblock_new(pool
, pa_frame_size(ss
) * 10));
135 d
= pa_memblock_acquire(r
);
137 switch (ss
->format
) {
141 case PA_SAMPLE_ALAW
: {
157 case PA_SAMPLE_S16NE
:
158 case PA_SAMPLE_S16RE
: {
174 case PA_SAMPLE_S32NE
:
175 case PA_SAMPLE_S32RE
: {
191 case PA_SAMPLE_S24_32NE
:
192 case PA_SAMPLE_S24_32RE
: {
208 case PA_SAMPLE_FLOAT32NE
:
209 case PA_SAMPLE_FLOAT32RE
: {
223 if (ss
->format
== PA_SAMPLE_FLOAT32RE
)
224 for (i
= 0; i
< 10; i
++)
225 u
[i
] = PA_FLOAT32_SWAP(u
[i
]);
230 case PA_SAMPLE_S24NE
:
231 case PA_SAMPLE_S24RE
: {
234 PA_WRITE24NE(u
, 0x000001);
235 PA_WRITE24NE(u
+3, 0xFF0002);
236 PA_WRITE24NE(u
+6, 0x7F0003);
237 PA_WRITE24NE(u
+9, 0x800004);
238 PA_WRITE24NE(u
+12, 0x9f0005);
239 PA_WRITE24NE(u
+15, 0x3f0006);
240 PA_WRITE24NE(u
+18, 0x107);
241 PA_WRITE24NE(u
+21, 0xF00008);
242 PA_WRITE24NE(u
+24, 0x2009);
243 PA_WRITE24NE(u
+27, 0x210A);
248 pa_assert_not_reached();
251 pa_memblock_release(r
);
256 static void help(const char *argv0
) {
257 printf(_("%s [options]\n\n"
258 "-h, --help Show this help\n"
259 "-v, --verbose Print debug messages\n"
260 " --from-rate=SAMPLERATE From sample rate in Hz (defaults to 44100)\n"
261 " --from-format=SAMPLEFORMAT From sample type (defaults to s16le)\n"
262 " --from-channels=CHANNELS From number of channels (defaults to 1)\n"
263 " --to-rate=SAMPLERATE To sample rate in Hz (defaults to 44100)\n"
264 " --to-format=SAMPLEFORMAT To sample type (defaults to s16le)\n"
265 " --to-channels=CHANNELS To number of channels (defaults to 1)\n"
266 " --resample-method=METHOD Resample method (defaults to auto)\n"
267 " --seconds=SECONDS From stream duration (defaults to 60)\n"
269 "If the formats are not specified, the test performs all formats combinations,\n"
272 "Sample type must be one of s16le, s16be, u8, float32le, float32be, ulaw, alaw,\n"
273 "s24le, s24be, s24-32le, s24-32be, s32le, s32be (defaults to s16ne)\n"
275 "See --dump-resample-methods for possible values of resample methods.\n"),
282 ARG_FROM_SAMPLEFORMAT
,
289 ARG_DUMP_RESAMPLE_METHODS
292 static void dump_resample_methods(void) {
295 for (i
= 0; i
< PA_RESAMPLER_MAX
; i
++)
296 if (pa_resample_method_supported(i
))
297 printf("%s\n", pa_resample_method_to_string(i
));
301 int main(int argc
, char *argv
[]) {
302 pa_mempool
*pool
= NULL
;
305 bool all_formats
= true;
306 pa_resample_method_t method
;
309 static const struct option long_options
[] = {
310 {"help", 0, NULL
, 'h'},
311 {"verbose", 0, NULL
, 'v'},
312 {"version", 0, NULL
, ARG_VERSION
},
313 {"from-rate", 1, NULL
, ARG_FROM_SAMPLERATE
},
314 {"from-format", 1, NULL
, ARG_FROM_SAMPLEFORMAT
},
315 {"from-channels", 1, NULL
, ARG_FROM_CHANNELS
},
316 {"to-rate", 1, NULL
, ARG_TO_SAMPLERATE
},
317 {"to-format", 1, NULL
, ARG_TO_SAMPLEFORMAT
},
318 {"to-channels", 1, NULL
, ARG_TO_CHANNELS
},
319 {"seconds", 1, NULL
, ARG_SECONDS
},
320 {"resample-method", 1, NULL
, ARG_RESAMPLE_METHOD
},
321 {"dump-resample-methods", 0, NULL
, ARG_DUMP_RESAMPLE_METHODS
},
325 setlocale(LC_ALL
, "");
327 bindtextdomain(GETTEXT_PACKAGE
, PULSE_LOCALEDIR
);
330 pa_log_set_level(PA_LOG_WARN
);
331 if (!getenv("MAKE_CHECK"))
332 pa_log_set_level(PA_LOG_INFO
);
334 pa_assert_se(pool
= pa_mempool_new(false, 0));
336 a
.channels
= b
.channels
= 1;
337 a
.rate
= b
.rate
= 44100;
338 a
.format
= b
.format
= PA_SAMPLE_S16LE
;
340 method
= PA_RESAMPLER_AUTO
;
343 while ((c
= getopt_long(argc
, argv
, "hv", long_options
, NULL
)) != -1) {
352 pa_log_set_level(PA_LOG_DEBUG
);
356 printf(_("%s %s\n"), argv
[0], PACKAGE_VERSION
);
360 case ARG_DUMP_RESAMPLE_METHODS
:
361 dump_resample_methods();
365 case ARG_FROM_CHANNELS
:
366 a
.channels
= (uint8_t) atoi(optarg
);
369 case ARG_FROM_SAMPLEFORMAT
:
370 a
.format
= pa_parse_sample_format(optarg
);
374 case ARG_FROM_SAMPLERATE
:
375 a
.rate
= (uint32_t) atoi(optarg
);
378 case ARG_TO_CHANNELS
:
379 b
.channels
= (uint8_t) atoi(optarg
);
382 case ARG_TO_SAMPLEFORMAT
:
383 b
.format
= pa_parse_sample_format(optarg
);
387 case ARG_TO_SAMPLERATE
:
388 b
.rate
= (uint32_t) atoi(optarg
);
392 seconds
= atoi(optarg
);
395 case ARG_RESAMPLE_METHOD
:
396 if (*optarg
== '\0' || pa_streq(optarg
, "help")) {
397 dump_resample_methods();
401 method
= pa_parse_resample_method(optarg
);
410 pa_assert_se(pool
= pa_mempool_new(false, 0));
414 pa_resampler
*resampler
;
418 pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS
);
419 pa_log_debug(_("=== %d seconds: %d Hz %d ch (%s) -> %d Hz %d ch (%s)"), seconds
,
420 a
.rate
, a
.channels
, pa_sample_format_to_string(a
.format
),
421 b
.rate
, b
.channels
, pa_sample_format_to_string(b
.format
));
423 ts
= pa_rtclock_now();
424 pa_assert_se(resampler
= pa_resampler_new(pool
, &a
, NULL
, &b
, NULL
, method
, 0));
425 pa_log_info("init: %llu", (long long unsigned)(pa_rtclock_now() - ts
));
427 i
.memblock
= pa_memblock_new(pool
, pa_usec_to_bytes(1*PA_USEC_PER_SEC
, &a
));
429 ts
= pa_rtclock_now();
430 i
.length
= pa_memblock_get_length(i
.memblock
);
433 pa_resampler_run(resampler
, &i
, &j
);
435 pa_memblock_unref(j
.memblock
);
437 pa_log_info("resampling: %llu", (long long unsigned)(pa_rtclock_now() - ts
));
438 pa_memblock_unref(i
.memblock
);
440 pa_resampler_free(resampler
);
445 for (a
.format
= 0; a
.format
< PA_SAMPLE_MAX
; a
.format
++) {
446 for (b
.format
= 0; b
.format
< PA_SAMPLE_MAX
; b
.format
++) {
447 pa_resampler
*forth
, *back
;
450 pa_log_debug("=== %s -> %s -> %s -> /2",
451 pa_sample_format_to_string(a
.format
),
452 pa_sample_format_to_string(b
.format
),
453 pa_sample_format_to_string(a
.format
));
455 pa_assert_se(forth
= pa_resampler_new(pool
, &a
, NULL
, &b
, NULL
, method
, 0));
456 pa_assert_se(back
= pa_resampler_new(pool
, &b
, NULL
, &a
, NULL
, method
, 0));
458 i
.memblock
= generate_block(pool
, &a
);
459 i
.length
= pa_memblock_get_length(i
.memblock
);
461 pa_resampler_run(forth
, &i
, &j
);
462 pa_resampler_run(back
, &j
, &k
);
464 dump_block("before", &a
, &i
);
465 dump_block("after", &b
, &j
);
466 dump_block("reverse", &a
, &k
);
468 pa_memblock_unref(i
.memblock
);
469 pa_memblock_unref(j
.memblock
);
470 pa_memblock_unref(k
.memblock
);
472 pa_resampler_free(forth
);
473 pa_resampler_free(back
);
479 pa_mempool_free(pool
);