Skip to content

Commit b8076e1

Browse files
author
Raphaël Droz
committed
sox -t pulseaudio depends upon pulseaudio buffering.
By default buffer size computation leads to (very) significant latencies (up to 2 sec) A confidential solution for the happy fews is to rely on the PULSE_LATENCY_MSEC environment variable. This commit publicly exposes pulseaudio in/out buffers by binding them to `sox --[input]-buffer` options. With `sox --input-buffer=40000 -t pulseaudio default -t pulseaudio default` you now get a low-latency pipeline. Notes: * Since --input-buffer defaults to 0, the default (high-latency) behavior stays unchanged (if PULSE_LATENCY_MSEC isn't set) * Since --buffer default to 8192 and can't be set to 0, it'll now have priority over PULSE_LATENCY_MSEC (for the playback stream)
1 parent dd8b63b commit b8076e1

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

src/pulseaudio.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
#include <pulse/simple.h>
99
#include <pulse/error.h>
10+
#include <pulse/timeval.h>
11+
12+
#define pa_memzero(x,l) (memset((x), 0, (l)))
13+
#define pa_zero(x) (pa_memzero(&(x), sizeof(x)))
1014

1115
typedef struct {
1216
pa_simple *pasp;
@@ -20,6 +24,13 @@ static int setup(sox_format_t *ft, int is_input)
2024
char *app_str;
2125
char *dev;
2226
pa_sample_spec spec;
27+
28+
/* Pulseaudio will introduce a 250ms buffer if no buffer_attr is set
29+
(https://github.com/pulseaudio/pulseaudio/blob/master/src/pulse/stream.c#L1028)
30+
unless PULSE_LATENCY_MSEC environment variable is set.
31+
Here we override this based on --input-buffer / --buffer command-line arguments
32+
*/
33+
pa_buffer_attr buffer_attr;
2334
int error;
2435

2536
/* TODO: If user specified device of type "server:dev" then
@@ -62,8 +73,24 @@ static int setup(sox_format_t *ft, int is_input)
6273
spec.rate = ft->signal.rate;
6374
spec.channels = ft->signal.channels;
6475

76+
pa_zero(buffer_attr);
77+
buffer_attr.maxlength = (uint32_t) -1;
78+
buffer_attr.prebuf = (uint32_t) -1;
79+
if (is_input) {
80+
/* If the tlength/fragsize is not set, pulseaudio src/pulse/stream.c will
81+
attempt to use getenv("PULSE_LATENCY_MSEC") and fallback on 250ms what
82+
is likely to happen for the default pulseaudio input (--input-buffer defaults to 0)
83+
ToDo: Add a pacat/parec-like --latency-msec option?
84+
*/
85+
buffer_attr.fragsize = sox_globals.input_bufsiz ? sox_globals.input_bufsiz : -1;
86+
lsx_debug("INPUT cmd buffer size=%zu, pulseaudio buffer size=%u", sox_globals.input_bufsiz, buffer_attr.fragsize);
87+
} else {
88+
buffer_attr.tlength = sox_globals.bufsiz ? sox_globals.bufsiz : -1;
89+
lsx_debug("OUTPUT cmd buffer size=%zu, pulseaudio buffer size=%u", sox_globals.bufsiz, buffer_attr.tlength);
90+
}
91+
6592
pa->pasp = pa_simple_new(server, "SoX", dir, dev, app_str, &spec,
66-
NULL, NULL, &error);
93+
NULL, &buffer_attr, &error);
6794

6895
if (pa->pasp == NULL)
6996
{

0 commit comments

Comments
 (0)