[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
- [PATCH v2 10/17] audio: wire up st_rate_frames_in(), (continued)
- [PATCH v2 10/17] audio: wire up st_rate_frames_in(), Volker Rümelin, 2023/02/06
- [PATCH v2 11/17] audio: replace the resampling loop in audio_pcm_sw_read(), Volker Rümelin, 2023/02/06
- [PATCH v2 04/17] audio: replace the resampling loop in audio_pcm_sw_write(), Volker Rümelin, 2023/02/06
- [PATCH v2 12/17] audio: rename variables in audio_pcm_sw_read(), Volker Rümelin, 2023/02/06
- [PATCH v2 13/17] audio/mixeng: calculate number of output frames, Volker Rümelin, 2023/02/06
- [PATCH v2 15/17] audio: handle leftover audio frame from upsampling, Volker Rümelin, 2023/02/06
- Re: [PATCH v2 15/17] audio: handle leftover audio frame from upsampling,
Marc-André Lureau <=
- [PATCH v2 14/17] audio: wire up st_rate_frames_out(), Volker Rümelin, 2023/02/06
- [PATCH v2 17/17] audio: remove sw->ratio, Volker Rümelin, 2023/02/06
- [PATCH v2 16/17] audio/audio_template: substitute sw->hw with hw, Volker Rümelin, 2023/02/06