[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 16/27] audio: replace the resampling loop in audio_pcm_sw_write()
From: |
marcandre . lureau |
Subject: |
[PULL 16/27] audio: replace the resampling loop in audio_pcm_sw_write() |
Date: |
Mon, 6 Mar 2023 10:51:51 +0400 |
From: Volker Rümelin <vr_qemu@t-online.de>
Replace the resampling loop in audio_pcm_sw_write() with the new
function audio_pcm_sw_resample_out(). Unlike the old resample
loop the new function will try to consume input frames even if
the output buffer is full. This is necessary when downsampling
to avoid reading less audio frames than calculated in advance.
The loop was unrolled to avoid complicated loop control conditions
in this case.
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
Message-Id: <20230224190555.7409-4-vr_qemu@t-online.de>
---
audio/audio.c | 63 +++++++++++++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 27 deletions(-)
diff --git a/audio/audio.c b/audio/audio.c
index a399147486..4412b5fad8 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -673,11 +673,44 @@ static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void
*pcm_buf, size_t len)
/*
* Soft voice (playback)
*/
+static void audio_pcm_sw_resample_out(SWVoiceOut *sw,
+ size_t frames_in_max, size_t frames_out_max,
+ size_t *total_in, size_t *total_out)
+{
+ HWVoiceOut *hw = sw->hw;
+ struct st_sample *src, *dst;
+ size_t live, wpos, frames_in, frames_out;
+
+ live = sw->total_hw_samples_mixed;
+ wpos = (hw->mix_buf.pos + live) % hw->mix_buf.size;
+
+ /* write to mix_buf from wpos to end of buffer */
+ src = sw->resample_buf.buffer;
+ frames_in = frames_in_max;
+ dst = hw->mix_buf.buffer + wpos;
+ frames_out = MIN(frames_out_max, hw->mix_buf.size - wpos);
+ st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
+ wpos += frames_out;
+ *total_in = frames_in;
+ *total_out = frames_out;
+
+ /* write to mix_buf from start of buffer if there are input frames left */
+ if (frames_in_max - frames_in > 0 && wpos == hw->mix_buf.size) {
+ src += frames_in;
+ frames_in = frames_in_max - frames_in;
+ dst = hw->mix_buf.buffer;
+ frames_out = frames_out_max - frames_out;
+ st_rate_flow_mix(sw->rate, src, dst, &frames_in, &frames_out);
+ *total_in += frames_in;
+ *total_out += frames_out;
+ }
+}
+
static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size)
{
- size_t hwsamples, samples, isamp, osamp, wpos, live, dead, left, blck;
+ size_t hwsamples, samples, live, dead;
size_t hw_free;
- size_t ret = 0, pos = 0, total = 0;
+ size_t ret, total;
if (!sw) {
return size;
@@ -698,8 +731,6 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf,
size_t size)
return 0;
}
- wpos = (sw->hw->mix_buf.pos + live) % hwsamples;
-
dead = hwsamples - live;
hw_free = audio_pcm_hw_get_free(sw->hw);
hw_free = hw_free > live ? hw_free - live : 0;
@@ -713,29 +744,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void
*buf, size_t size)
}
}
- while (samples) {
- dead = hwsamples - live;
- left = hwsamples - wpos;
- blck = MIN (dead, left);
- if (!blck) {
- break;
- }
- isamp = samples;
- osamp = blck;
- st_rate_flow_mix (
- sw->rate,
- sw->resample_buf.buffer + pos,
- sw->hw->mix_buf.buffer + wpos,
- &isamp,
- &osamp
- );
- ret += isamp;
- samples -= isamp;
- pos += isamp;
- live += osamp;
- wpos = (wpos + osamp) % hwsamples;
- total += osamp;
- }
+ audio_pcm_sw_resample_out(sw, samples, MIN(dead, hw_free), &ret, &total);
sw->total_hw_samples_mixed += total;
sw->empty = sw->total_hw_samples_mixed == 0;
--
2.39.2
- [PULL 06/27] audio/mixeng: use g_new0() instead of audio_calloc(), (continued)
- [PULL 06/27] audio/mixeng: use g_new0() instead of audio_calloc(), marcandre . lureau, 2023/03/06
- [PULL 09/27] audio/audio_template: use g_new0() to replace audio_calloc(), marcandre . lureau, 2023/03/06
- [PULL 07/27] audio/alsaaudio: use g_new0() instead of audio_calloc(), marcandre . lureau, 2023/03/06
- [PULL 10/27] audio: remove audio_calloc() function, marcandre . lureau, 2023/03/06
- [PULL 08/27] audio/audio_template: use g_malloc0() to replace audio_calloc(), marcandre . lureau, 2023/03/06
- [PULL 11/27] alsaaudio: change default playback settings, marcandre . lureau, 2023/03/06
- [PULL 12/27] alsaaudio: reintroduce default recording settings, marcandre . lureau, 2023/03/06
- [PULL 13/27] audio: change type of mix_buf and conv_buf, marcandre . lureau, 2023/03/06
- [PULL 14/27] audio: change type and name of the resample buffer, marcandre . lureau, 2023/03/06
- [PULL 15/27] audio: make the resampling code greedy, marcandre . lureau, 2023/03/06
- [PULL 16/27] audio: replace the resampling loop in audio_pcm_sw_write(),
marcandre . lureau <=
- [PULL 17/27] audio: remove sw == NULL check, marcandre . lureau, 2023/03/06
- [PULL 18/27] audio: rename variables in audio_pcm_sw_write(), marcandre . lureau, 2023/03/06
- [PULL 19/27] audio: don't misuse audio_pcm_sw_write(), marcandre . lureau, 2023/03/06
- [PULL 20/27] audio: remove unused noop_conv() function, marcandre . lureau, 2023/03/06
- [PULL 22/27] audio: replace the resampling loop in audio_pcm_sw_read(), marcandre . lureau, 2023/03/06
- [PULL 21/27] audio: make playback packet length calculation exact, marcandre . lureau, 2023/03/06
- [PULL 23/27] audio: rename variables in audio_pcm_sw_read(), marcandre . lureau, 2023/03/06
- [PULL 24/27] audio: make recording packet length calculation exact, marcandre . lureau, 2023/03/06
- [PULL 25/27] audio: handle leftover audio frame from upsampling, marcandre . lureau, 2023/03/06
- [PULL 26/27] audio/audio_template: substitute sw->hw with hw, marcandre . lureau, 2023/03/06