diff mbox series

[04/12] alsaaudio: reduce playback latency

Message ID 20220923183640.8314-4-vr_qemu@t-online.de (mailing list archive)
State New, archived
Headers show
Series audio: misc. improvements and bug fixes | expand

Commit Message

Volker Rümelin Sept. 23, 2022, 6:36 p.m. UTC
Change the buffer_get_free pcm_ops function to report the free
ALSA playback buffer. The generic buffer becomes a temporary
buffer and is empty after a call to audio_run_out().

Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
---
 audio/alsaaudio.c | 38 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

Comments

Marc-André Lureau Sept. 27, 2022, 11:54 a.m. UTC | #1
On Fri, Sep 23, 2022 at 10:51 PM Volker Rümelin <vr_qemu@t-online.de> wrote:

> Change the buffer_get_free pcm_ops function to report the free
> ALSA playback buffer. The generic buffer becomes a temporary
> buffer and is empty after a call to audio_run_out().
>
> Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
>

lgtm
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>


> ---
>  audio/alsaaudio.c | 38 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 37 insertions(+), 1 deletion(-)
>
> diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
> index 4a61378cd7..7a2a94cd42 100644
> --- a/audio/alsaaudio.c
> +++ b/audio/alsaaudio.c
> @@ -602,6 +602,42 @@ static int alsa_open(bool in, struct alsa_params_req
> *req,
>      return -1;
>  }
>
> +static size_t alsa_buffer_get_free(HWVoiceOut *hw)
> +{
> +    ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
> +    snd_pcm_sframes_t avail;
> +    size_t alsa_free, generic_free, generic_in_use;
> +
> +    avail = snd_pcm_avail_update(alsa->handle);
> +    if (avail < 0) {
> +        if (avail == -EPIPE) {
> +            if (!alsa_recover(alsa->handle)) {
> +                avail = snd_pcm_avail_update(alsa->handle);
> +            }
> +        }
> +        if (avail < 0) {
> +            alsa_logerr(avail,
> +                        "Could not obtain number of available frames\n");
> +            avail = 0;
> +        }
> +    }
> +
> +    alsa_free = avail * hw->info.bytes_per_frame;
> +    generic_free = audio_generic_buffer_get_free(hw);
> +    generic_in_use = hw->samples * hw->info.bytes_per_frame -
> generic_free;
> +    if (generic_in_use) {
> +        /*
> +         * This code can only be reached in the unlikely case that
> +         * snd_pcm_avail_update() returned a larger number of frames
> +         * than snd_pcm_writei() could write. Make sure that all
> +         * remaining bytes in the generic buffer can be written.
> +         */
> +        alsa_free = alsa_free > generic_in_use ? alsa_free -
> generic_in_use : 0;
> +    }
> +
> +    return alsa_free;
> +}
> +
>  static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
>  {
>      ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
> @@ -916,7 +952,7 @@ static struct audio_pcm_ops alsa_pcm_ops = {
>      .init_out = alsa_init_out,
>      .fini_out = alsa_fini_out,
>      .write    = alsa_write,
> -    .buffer_get_free = audio_generic_buffer_get_free,
> +    .buffer_get_free = alsa_buffer_get_free,
>      .run_buffer_out = audio_generic_run_buffer_out,
>      .enable_out = alsa_enable_out,
>
> --
> 2.35.3
>
>
>
diff mbox series

Patch

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 4a61378cd7..7a2a94cd42 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -602,6 +602,42 @@  static int alsa_open(bool in, struct alsa_params_req *req,
     return -1;
 }
 
+static size_t alsa_buffer_get_free(HWVoiceOut *hw)
+{
+    ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
+    snd_pcm_sframes_t avail;
+    size_t alsa_free, generic_free, generic_in_use;
+
+    avail = snd_pcm_avail_update(alsa->handle);
+    if (avail < 0) {
+        if (avail == -EPIPE) {
+            if (!alsa_recover(alsa->handle)) {
+                avail = snd_pcm_avail_update(alsa->handle);
+            }
+        }
+        if (avail < 0) {
+            alsa_logerr(avail,
+                        "Could not obtain number of available frames\n");
+            avail = 0;
+        }
+    }
+
+    alsa_free = avail * hw->info.bytes_per_frame;
+    generic_free = audio_generic_buffer_get_free(hw);
+    generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free;
+    if (generic_in_use) {
+        /*
+         * This code can only be reached in the unlikely case that
+         * snd_pcm_avail_update() returned a larger number of frames
+         * than snd_pcm_writei() could write. Make sure that all
+         * remaining bytes in the generic buffer can be written.
+         */
+        alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0;
+    }
+
+    return alsa_free;
+}
+
 static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
 {
     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
@@ -916,7 +952,7 @@  static struct audio_pcm_ops alsa_pcm_ops = {
     .init_out = alsa_init_out,
     .fini_out = alsa_fini_out,
     .write    = alsa_write,
-    .buffer_get_free = audio_generic_buffer_get_free,
+    .buffer_get_free = alsa_buffer_get_free,
     .run_buffer_out = audio_generic_run_buffer_out,
     .enable_out = alsa_enable_out,