From 4947bb113d26045f5fa0e5800db73acd75500109 Mon Sep 17 00:00:00 2001 From: borine <32966433+borine@users.noreply.github.com> Date: Sat, 6 May 2023 08:40:07 +0100 Subject: [PATCH] input/plugins/Alsa: limit ALSA buffer time to 2 seconds maximum Some ALSA capture devices can have very large buffers, holding 10 seconds or more audio. Using the maximum buffer size with such devices leads to unacceptably large, and unnecessary, latency. Also, some ALSA drivers (e.g. HDA Intel PCH) report an invalid maximum period size, and the period size that mpd calculates from the maximum buffer size results in "Invalid argument" error when applying the hw_params. Note that the "default" capture device on many cards includes the "dsnoop" plugin which imposes a buffer size of 16384 frames, so that "alsa://" works OK but "alsa://plughw" or "alsa://hw" both fail. Limit the maximum buffer time for ALSA input devices to a more useable 2 seconds, thereby avoiding both the above problems. --- src/input/plugins/AlsaInputPlugin.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index ebc359595..06ff8649c 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -353,9 +353,14 @@ AlsaInputStream::ConfigureCapture(AudioFormat audio_format) period_size_min, period_size_max, period_time_min, period_time_max); - /* choose the maximum possible buffer_size ... */ - snd_pcm_hw_params_set_buffer_size(capture_handle, hw_params, - buffer_size_max); + /* choose the maximum buffer_time up to limit of 2 seconds ... */ + unsigned buffer_time = buffer_time_max; + if (buffer_time > 2000000U) + buffer_time = 2000000U; + int direction = -1; + if ((err = snd_pcm_hw_params_set_buffer_time_near(capture_handle, + hw_params, &buffer_time, &direction)) < 0) + throw Alsa::MakeError(err, "Cannot set buffer time"); /* ... and calculate the period_size to have four periods in one buffer; this way, we get woken up often enough to avoid @@ -363,7 +368,7 @@ AlsaInputStream::ConfigureCapture(AudioFormat audio_format) snd_pcm_uframes_t buffer_size; if (snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size) == 0) { snd_pcm_uframes_t period_size = buffer_size / 4; - int direction = -1; + direction = -1; if ((err = snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, &period_size, &direction)) < 0) throw Alsa::MakeError(err, "Cannot set period size");