[client] audio: make the requested audio device period size configurable

This adds a new `audio:periodSize` option which defaults to 2048 frames.
For PipeWire, this controls the `PIPEWIRE_LATENCY` value. For PulseAudio,
the controls the target buffer length (`tlength`) value.
This commit is contained in:
Chris Spencer
2022-02-20 21:27:22 +00:00
committed by Geoffrey McRae
parent 0dad9b1e76
commit 9908b737b0
6 changed files with 61 additions and 33 deletions

View File

@@ -39,6 +39,7 @@ struct PulseAudio
bool sinkMuted;
bool sinkStarting;
int sinkMaxPeriodFrames;
int sinkStartFrames;
int sinkSampleRate;
int sinkChannels;
int sinkStride;
@@ -257,29 +258,29 @@ static void pulseaudio_overflow_cb(pa_stream * p, void * userdata)
}
static void pulseaudio_setup(int channels, int sampleRate,
int * maxPeriodFrames, LG_AudioPullFn pullFn)
int requestedPeriodFrames, int * maxPeriodFrames, int * startFrames,
LG_AudioPullFn pullFn)
{
if (pa.sink && pa.sinkChannels == channels && pa.sinkSampleRate == sampleRate)
{
*maxPeriodFrames = pa.sinkMaxPeriodFrames;
*startFrames = pa.sinkStartFrames;
return;
}
//TODO: be smarter about this
const int PERIOD_LEN = 80;
pa_sample_spec spec = {
.format = PA_SAMPLE_FLOAT32,
.rate = sampleRate,
.channels = channels
};
int stride = channels * sizeof(float);
int bufferSize = requestedPeriodFrames * 2 * stride;
pa_buffer_attr attribs =
{
.maxlength = pa_usec_to_bytes((PERIOD_LEN * 2) * PA_USEC_PER_MSEC, &spec),
.tlength = pa_usec_to_bytes(PERIOD_LEN * PA_USEC_PER_MSEC, &spec),
.maxlength = -1,
.tlength = bufferSize,
.prebuf = 0,
.fragsize = pa_usec_to_bytes(PERIOD_LEN * PA_USEC_PER_MSEC, &spec),
.minreq = (uint32_t)-1
};
@@ -295,17 +296,21 @@ static void pulseaudio_setup(int channels, int sampleRate,
pa_stream_set_underflow_callback(pa.sink, pulseaudio_underflow_cb, NULL);
pa_stream_set_overflow_callback (pa.sink, pulseaudio_overflow_cb , NULL);
pa_stream_connect_playback(pa.sink, NULL, &attribs,
PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY,
pa_stream_connect_playback(pa.sink, NULL, &attribs, PA_STREAM_START_CORKED,
NULL, NULL);
pa.sinkStride = channels * sizeof(float);
pa.sinkStride = stride;
pa.sinkPullFn = pullFn;
pa.sinkMaxPeriodFrames = attribs.tlength / pa.sinkStride;
pa.sinkMaxPeriodFrames = requestedPeriodFrames;
pa.sinkCorked = true;
pa.sinkStarting = false;
*maxPeriodFrames = pa.sinkMaxPeriodFrames;
// If something else is, or was recently using a small latency value,
// PulseAudio can request way more data at startup than is reasonable
pa.sinkStartFrames = requestedPeriodFrames * 4;
*maxPeriodFrames = requestedPeriodFrames;
*startFrames = pa.sinkStartFrames;
pa_threaded_mainloop_unlock(pa.loop);
}