qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 15/17] audio: handle leftover audio frame from upsampling


From: Marc-André Lureau
Subject: Re: [PATCH v2 15/17] audio: handle leftover audio frame from upsampling
Date: Wed, 22 Feb 2023 14:50:19 +0400

On Mon, Feb 6, 2023 at 10:53 PM Volker Rümelin <vr_qemu@t-online.de> wrote:
>
> Upsampling may leave one remaining audio frame in the input
> buffer. The emulated audio playback devices are currently
> resposible to write this audio frame again in the next write
> cycle. Push that task down to audio_pcm_sw_write.
>
> This is another step towards an audio callback interface that
> guarantees that when audio frontends are told they can write
> n audio frames, they can actually do so.
>
> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>

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



> ---
>  audio/audio.c          | 34 ++++++++++++++++++++++++++++------
>  audio/audio_template.h |  6 ++++++
>  2 files changed, 34 insertions(+), 6 deletions(-)
>
> diff --git a/audio/audio.c b/audio/audio.c
> index dad17e59b8..4836ab8ca8 100644
> --- a/audio/audio.c
> +++ b/audio/audio.c
> @@ -731,16 +731,21 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void 
> *buf, size_t buf_len)
>      hw_free = hw_free > live ? hw_free - live : 0;
>      frames_out_max = MIN(dead, hw_free);
>      sw_max = st_rate_frames_in(sw->rate, frames_out_max);
> -    fe_max = MIN(buf_len / sw->info.bytes_per_frame, sw->resample_buf.size);
> +    fe_max = MIN(buf_len / sw->info.bytes_per_frame + sw->resample_buf.pos,
> +                 sw->resample_buf.size);
>      frames_in_max = MIN(sw_max, fe_max);
>
>      if (!frames_in_max) {
>          return 0;
>      }
>
> -    sw->conv(sw->resample_buf.buffer, buf, frames_in_max);
> -    if (!sw->hw->pcm_ops->volume_out) {
> -        mixeng_volume(sw->resample_buf.buffer, frames_in_max, &sw->vol);
> +    if (frames_in_max > sw->resample_buf.pos) {
> +        sw->conv(sw->resample_buf.buffer + sw->resample_buf.pos,
> +                 buf, frames_in_max - sw->resample_buf.pos);
> +        if (!sw->hw->pcm_ops->volume_out) {
> +            mixeng_volume(sw->resample_buf.buffer + sw->resample_buf.pos,
> +                          frames_in_max - sw->resample_buf.pos, &sw->vol);
> +        }
>      }
>
>      audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
> @@ -749,6 +754,22 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void 
> *buf, size_t buf_len)
>      sw->total_hw_samples_mixed += total_out;
>      sw->empty = sw->total_hw_samples_mixed == 0;
>
> +    /*
> +     * Upsampling may leave one audio frame in the resample buffer. Decrement
> +     * total_in by one if there was a leftover frame from the previous 
> resample
> +     * pass in the resample buffer. Increment total_in by one if the current
> +     * resample pass left one frame in the resample buffer.
> +     */
> +    if (frames_in_max - total_in == 1) {
> +        /* copy one leftover audio frame to the beginning of the buffer */
> +        *sw->resample_buf.buffer = *(sw->resample_buf.buffer + total_in);
> +        total_in += 1 - sw->resample_buf.pos;
> +        sw->resample_buf.pos = 1;
> +    } else if (total_in >= sw->resample_buf.pos) {
> +        total_in -= sw->resample_buf.pos;
> +        sw->resample_buf.pos = 0;
> +    }
> +
>  #ifdef DEBUG_OUT
>      dolog (
>          "%s: write size %zu written %zu total mixed %zu\n",
> @@ -1155,8 +1176,9 @@ static void audio_run_out (AudioState *s)
>                  } else {
>                      free = 0;
>                  }
> -                if (free > 0) {
> -                    free = MIN(free, sw->resample_buf.size);
> +                if (free > sw->resample_buf.pos) {
> +                    free = MIN(free, sw->resample_buf.size)
> +                           - sw->resample_buf.pos;
>                      sw->callback.fn(sw->callback.opaque,
>                                      free * sw->info.bytes_per_frame);
>                  }
> diff --git a/audio/audio_template.h b/audio/audio_template.h
> index a0b653f52c..0d8aab6fad 100644
> --- a/audio/audio_template.h
> +++ b/audio/audio_template.h
> @@ -138,6 +138,12 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) 
> (SW *sw)
>          return -1;
>      }
>
> +    /*
> +     * Allocate one additional audio frame that is needed for upsampling
> +     * if the resample buffer size is small. For large buffer sizes take
> +     * care of overflows.
> +     */
> +    samples = samples < INT_MAX ? samples + 1 : INT_MAX;
>      sw->resample_buf.buffer = g_new0(st_sample, samples);
>      sw->resample_buf.size = samples;
>      sw->resample_buf.pos = 0;
> --
> 2.35.3
>


--
Marc-André Lureau



reply via email to

[Prev in Thread] Current Thread [Next in Thread]