Re: [PATCH v3 10/15] audio: restore mixing-engine playback buffer size

2022-03-01 Thread Akihiko Odaki

Reviewed-by: Akihiko Odaki 

On 2022/03/02 4:13, Volker Rümelin wrote:

Commit ff095e5231 "audio: api for mixeng code free backends"
introduced another FIFO for the audio subsystem with exactly the
same size as the mixing-engine FIFO. Most audio backends use
this generic FIFO. The generic FIFO used together with the
mixing-engine FIFO doubles the audio FIFO size, because that's
just two independent FIFOs connected together in series.

For audio playback this nearly doubles the playback latency.

This patch restores the effective mixing-engine playback buffer
size to a pre v4.2.0 size by only accepting the amount of
samples for the mixing-engine queue which the downstream queue
accepts.

Signed-off-by: Volker Rümelin 
---
  audio/alsaaudio.c |  1 +
  audio/audio.c | 69 +++
  audio/audio_int.h |  7 -
  audio/coreaudio.c |  3 +++
  audio/jackaudio.c |  1 +
  audio/noaudio.c   |  1 +
  audio/ossaudio.c  | 12 +
  audio/sdlaudio.c  |  3 +++
  audio/wavaudio.c  |  1 +
  9 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 2b9789e647..b04716a6cc 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -916,6 +916,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,
  .run_buffer_out = audio_generic_run_buffer_out,
  .enable_out = alsa_enable_out,
  
diff --git a/audio/audio.c b/audio/audio.c

index c420a8bd1c..a88572e713 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -663,6 +663,12 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, 
int *nb_live)
  return 0;
  }
  
+static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)

+{
+return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
+INT_MAX) / hw->info.bytes_per_frame;
+}
+
  static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
  {
  size_t clipped = 0;
@@ -687,7 +693,8 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void 
*pcm_buf, size_t len)
   */
  static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
  {
-size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, 
blck;
+size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
+size_t hw_free;
  size_t ret = 0, pos = 0, total = 0;
  
  if (!sw) {

@@ -710,27 +717,28 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void 
*buf, size_t size)
  }
  
  wpos = (sw->hw->mix_buf->pos + live) % hwsamples;

-samples = size / sw->info.bytes_per_frame;
  
  dead = hwsamples - live;

-swlim = ((int64_t) dead << 32) / sw->ratio;
-swlim = MIN (swlim, samples);
-if (swlim) {
-sw->conv (sw->buf, buf, swlim);
+hw_free = audio_pcm_hw_get_free(sw->hw);
+hw_free = hw_free > live ? hw_free - live : 0;
+samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
+samples = MIN(samples, size / sw->info.bytes_per_frame);
+if (samples) {
+sw->conv(sw->buf, buf, samples);
  
  if (!sw->hw->pcm_ops->volume_out) {

-mixeng_volume (sw->buf, swlim, >vol);
+mixeng_volume(sw->buf, samples, >vol);
  }
  }
  
-while (swlim) {

+while (samples) {
  dead = hwsamples - live;
  left = hwsamples - wpos;
  blck = MIN (dead, left);
  if (!blck) {
  break;
  }
-isamp = swlim;
+isamp = samples;
  osamp = blck;
  st_rate_flow_mix (
  sw->rate,
@@ -740,7 +748,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, 
size_t size)
  
  );
  ret += isamp;
-swlim -= isamp;
+samples -= isamp;
  pos += isamp;
  live += osamp;
  wpos = (wpos + osamp) % hwsamples;
@@ -1002,6 +1010,11 @@ static size_t audio_get_avail (SWVoiceIn *sw)
  return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
  }
  
+static size_t audio_sw_bytes_free(SWVoiceOut *sw, size_t free)

+{
+return (((int64_t)free << 32) / sw->ratio) * sw->info.bytes_per_frame;
+}
+
  static size_t audio_get_free(SWVoiceOut *sw)
  {
  size_t live, dead;
@@ -1021,13 +1034,11 @@ 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 ret %" PRId64 "\n",
-   SW_NAME (sw),
-   live, dead, (((int64_t) dead << 32) / sw->ratio) *
-   sw->info.bytes_per_frame);
+dolog("%s: get_free live %zu dead %zu sw_bytes %zu\n",
+  SW_NAME(sw), live, dead, audio_sw_bytes_free(sw, dead));
  #endif
  
-return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;

+return dead;
  }
  
  static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t 

[PATCH v3 10/15] audio: restore mixing-engine playback buffer size

2022-03-01 Thread Volker Rümelin
Commit ff095e5231 "audio: api for mixeng code free backends"
introduced another FIFO for the audio subsystem with exactly the
same size as the mixing-engine FIFO. Most audio backends use
this generic FIFO. The generic FIFO used together with the
mixing-engine FIFO doubles the audio FIFO size, because that's
just two independent FIFOs connected together in series.

For audio playback this nearly doubles the playback latency.

This patch restores the effective mixing-engine playback buffer
size to a pre v4.2.0 size by only accepting the amount of
samples for the mixing-engine queue which the downstream queue
accepts.

Signed-off-by: Volker Rümelin 
---
 audio/alsaaudio.c |  1 +
 audio/audio.c | 69 +++
 audio/audio_int.h |  7 -
 audio/coreaudio.c |  3 +++
 audio/jackaudio.c |  1 +
 audio/noaudio.c   |  1 +
 audio/ossaudio.c  | 12 +
 audio/sdlaudio.c  |  3 +++
 audio/wavaudio.c  |  1 +
 9 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 2b9789e647..b04716a6cc 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -916,6 +916,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,
 .run_buffer_out = audio_generic_run_buffer_out,
 .enable_out = alsa_enable_out,
 
diff --git a/audio/audio.c b/audio/audio.c
index c420a8bd1c..a88572e713 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -663,6 +663,12 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, 
int *nb_live)
 return 0;
 }
 
+static size_t audio_pcm_hw_get_free(HWVoiceOut *hw)
+{
+return (hw->pcm_ops->buffer_get_free ? hw->pcm_ops->buffer_get_free(hw) :
+INT_MAX) / hw->info.bytes_per_frame;
+}
+
 static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
 {
 size_t clipped = 0;
@@ -687,7 +693,8 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void 
*pcm_buf, size_t len)
  */
 static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
 {
-size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, 
blck;
+size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
+size_t hw_free;
 size_t ret = 0, pos = 0, total = 0;
 
 if (!sw) {
@@ -710,27 +717,28 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void 
*buf, size_t size)
 }
 
 wpos = (sw->hw->mix_buf->pos + live) % hwsamples;
-samples = size / sw->info.bytes_per_frame;
 
 dead = hwsamples - live;
-swlim = ((int64_t) dead << 32) / sw->ratio;
-swlim = MIN (swlim, samples);
-if (swlim) {
-sw->conv (sw->buf, buf, swlim);
+hw_free = audio_pcm_hw_get_free(sw->hw);
+hw_free = hw_free > live ? hw_free - live : 0;
+samples = ((int64_t)MIN(dead, hw_free) << 32) / sw->ratio;
+samples = MIN(samples, size / sw->info.bytes_per_frame);
+if (samples) {
+sw->conv(sw->buf, buf, samples);
 
 if (!sw->hw->pcm_ops->volume_out) {
-mixeng_volume (sw->buf, swlim, >vol);
+mixeng_volume(sw->buf, samples, >vol);
 }
 }
 
-while (swlim) {
+while (samples) {
 dead = hwsamples - live;
 left = hwsamples - wpos;
 blck = MIN (dead, left);
 if (!blck) {
 break;
 }
-isamp = swlim;
+isamp = samples;
 osamp = blck;
 st_rate_flow_mix (
 sw->rate,
@@ -740,7 +748,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, 
size_t size)
 
 );
 ret += isamp;
-swlim -= isamp;
+samples -= isamp;
 pos += isamp;
 live += osamp;
 wpos = (wpos + osamp) % hwsamples;
@@ -1002,6 +1010,11 @@ static size_t audio_get_avail (SWVoiceIn *sw)
 return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
 }
 
+static size_t audio_sw_bytes_free(SWVoiceOut *sw, size_t free)
+{
+return (((int64_t)free << 32) / sw->ratio) * sw->info.bytes_per_frame;
+}
+
 static size_t audio_get_free(SWVoiceOut *sw)
 {
 size_t live, dead;
@@ -1021,13 +1034,11 @@ 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 ret %" PRId64 "\n",
-   SW_NAME (sw),
-   live, dead, (((int64_t) dead << 32) / sw->ratio) *
-   sw->info.bytes_per_frame);
+dolog("%s: get_free live %zu dead %zu sw_bytes %zu\n",
+  SW_NAME(sw), live, dead, audio_sw_bytes_free(sw, dead));
 #endif
 
-return (((int64_t) dead << 32) / sw->ratio) * sw->info.bytes_per_frame;
+return dead;
 }
 
 static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos,
@@ -1131,12 +1142,21 @@ static void audio_run_out (AudioState *s)
 }
 
 while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
-