diff mbox series

[v2,10/17] audio: wire up st_rate_frames_in()

Message ID 20230206185237.8358-10-vr_qemu@t-online.de
State New
Headers show
Series audio: improve callback interface for audio frontends | expand

Commit Message

Volker Rümelin Feb. 6, 2023, 6:52 p.m. UTC
Wire up the st_rate_frames_in() function and replace
audio_frontend_frames_out() to make audio packet length
calculation exact. When upsampling, it's still possible that
the audio frontends can't write the last audio frame. This will
be fixed later.

Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
---
 audio/audio.c | 43 ++++++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 25 deletions(-)

Comments

Marc-André Lureau Feb. 22, 2023, 10:50 a.m. UTC | #1
Hi

On Mon, Feb 6, 2023 at 10:53 PM Volker Rümelin <vr_qemu@t-online.de> wrote:
>
> Wire up the st_rate_frames_in() function and replace
> audio_frontend_frames_out() to make audio packet length
> calculation exact. When upsampling, it's still possible that
> the audio frontends can't write the last audio frame. This will
> be fixed later.
>
> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>

I think you should squash it with the previous patch and detail the
differences of computation (the code comment of the functions should
reflect the change, that would help ;)


> ---
>  audio/audio.c | 43 ++++++++++++++++++-------------------------
>  1 file changed, 18 insertions(+), 25 deletions(-)
>
> diff --git a/audio/audio.c b/audio/audio.c
> index 556696b095..e18b5e98c5 100644
> --- a/audio/audio.c
> +++ b/audio/audio.c
> @@ -701,8 +701,8 @@ static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
>  static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
>  {
>      HWVoiceOut *hw = sw->hw;
> -    size_t live, dead, hw_free;
> -    size_t frames_in_max, total_in, total_out;
> +    size_t live, dead, hw_free, sw_max, fe_max;
> +    size_t frames_in_max, frames_out_max, total_in, total_out;
>
>      live = sw->total_hw_samples_mixed;
>      if (audio_bug(__func__, live > hw->mix_buf.size)) {
> @@ -720,17 +720,21 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
>      dead = hw->mix_buf.size - live;
>      hw_free = audio_pcm_hw_get_free(hw);
>      hw_free = hw_free > live ? hw_free - live : 0;
> -    frames_in_max = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
> -    frames_in_max = MIN(frames_in_max, buf_len / sw->info.bytes_per_frame);
> -    if (frames_in_max) {
> -        sw->conv(sw->resample_buf.buffer, buf, frames_in_max);
> +    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);
> +    frames_in_max = MIN(sw_max, fe_max);
>
> -        if (!sw->hw->pcm_ops->volume_out) {
> -            mixeng_volume(sw->resample_buf.buffer, frames_in_max, &sw->vol);
> -        }
> +    if (!frames_in_max) {
> +        return 0;
>      }
>
> -    audio_pcm_sw_resample_out(sw, frames_in_max, MIN(dead, hw_free),
> +    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);
> +    }
> +
> +    audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
>                                &total_in, &total_out);
>
>      sw->total_hw_samples_mixed += total_out;
> @@ -1000,18 +1004,6 @@ static size_t audio_get_avail (SWVoiceIn *sw)
>      return live;
>  }
>
> -/**
> - * audio_frontend_frames_out() - returns the number of frames needed to
> - * get frames_out frames after resampling
> - *
> - * @sw: audio playback frontend
> - * @frames_out: number of frames
> - */
> -static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
> -{
> -    return ((int64_t)frames_out << 32) / sw->ratio;
> -}
> -
>  static size_t audio_get_free(SWVoiceOut *sw)
>  {
>      size_t live, dead;
> @@ -1031,8 +1023,8 @@ static size_t audio_get_free(SWVoiceOut *sw)
>      dead = sw->hw->mix_buf.size - live;
>
>  #ifdef DEBUG_OUT
> -    dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
> -          SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
> +    dolog("%s: get_free live %zu dead %zu frontend frames %u\n",
> +          SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead));
>  #endif
>
>      return dead;
> @@ -1161,12 +1153,13 @@ static void audio_run_out (AudioState *s)
>                  size_t free;
>
>                  if (hw_free > sw->total_hw_samples_mixed) {
> -                    free = audio_frontend_frames_out(sw,
> +                    free = st_rate_frames_in(sw->rate,
>                          MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
>                  } else {
>                      free = 0;
>                  }
>                  if (free > 0) {
> +                    free = MIN(free, sw->resample_buf.size);
>                      sw->callback.fn(sw->callback.opaque,
>                                      free * sw->info.bytes_per_frame);
>                  }
> --
> 2.35.3
>


--
Marc-André Lureau
diff mbox series

Patch

diff --git a/audio/audio.c b/audio/audio.c
index 556696b095..e18b5e98c5 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -701,8 +701,8 @@  static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
 static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
 {
     HWVoiceOut *hw = sw->hw;
-    size_t live, dead, hw_free;
-    size_t frames_in_max, total_in, total_out;
+    size_t live, dead, hw_free, sw_max, fe_max;
+    size_t frames_in_max, frames_out_max, total_in, total_out;
 
     live = sw->total_hw_samples_mixed;
     if (audio_bug(__func__, live > hw->mix_buf.size)) {
@@ -720,17 +720,21 @@  static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t buf_len)
     dead = hw->mix_buf.size - live;
     hw_free = audio_pcm_hw_get_free(hw);
     hw_free = hw_free > live ? hw_free - live : 0;
-    frames_in_max = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
-    frames_in_max = MIN(frames_in_max, buf_len / sw->info.bytes_per_frame);
-    if (frames_in_max) {
-        sw->conv(sw->resample_buf.buffer, buf, frames_in_max);
+    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);
+    frames_in_max = MIN(sw_max, fe_max);
 
-        if (!sw->hw->pcm_ops->volume_out) {
-            mixeng_volume(sw->resample_buf.buffer, frames_in_max, &sw->vol);
-        }
+    if (!frames_in_max) {
+        return 0;
     }
 
-    audio_pcm_sw_resample_out(sw, frames_in_max, MIN(dead, hw_free),
+    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);
+    }
+
+    audio_pcm_sw_resample_out(sw, frames_in_max, frames_out_max,
                               &total_in, &total_out);
 
     sw->total_hw_samples_mixed += total_out;
@@ -1000,18 +1004,6 @@  static size_t audio_get_avail (SWVoiceIn *sw)
     return live;
 }
 
-/**
- * audio_frontend_frames_out() - returns the number of frames needed to
- * get frames_out frames after resampling
- *
- * @sw: audio playback frontend
- * @frames_out: number of frames
- */
-static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
-{
-    return ((int64_t)frames_out << 32) / sw->ratio;
-}
-
 static size_t audio_get_free(SWVoiceOut *sw)
 {
     size_t live, dead;
@@ -1031,8 +1023,8 @@  static size_t audio_get_free(SWVoiceOut *sw)
     dead = sw->hw->mix_buf.size - live;
 
 #ifdef DEBUG_OUT
-    dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
-          SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
+    dolog("%s: get_free live %zu dead %zu frontend frames %u\n",
+          SW_NAME(sw), live, dead, st_rate_frames_in(sw->rate, dead));
 #endif
 
     return dead;
@@ -1161,12 +1153,13 @@  static void audio_run_out (AudioState *s)
                 size_t free;
 
                 if (hw_free > sw->total_hw_samples_mixed) {
-                    free = audio_frontend_frames_out(sw,
+                    free = st_rate_frames_in(sw->rate,
                         MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
                 } else {
                     free = 0;
                 }
                 if (free > 0) {
+                    free = MIN(free, sw->resample_buf.size);
                     sw->callback.fn(sw->callback.opaque,
                                     free * sw->info.bytes_per_frame);
                 }