From: "Volker Rümelin" <vr_qemu@t-online.de>
To: "Gerd Hoffmann" <kraxel@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@gmail.com>
Cc: qemu-devel@nongnu.org,
Christian Schoenebeck <qemu_oss@crudebyte.com>,
Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Subject: [PATCH v2 04/17] audio: replace the resampling loop in audio_pcm_sw_write()
Date: Mon, 6 Feb 2023 19:52:24 +0100 [thread overview]
Message-ID: <20230206185237.8358-4-vr_qemu@t-online.de> (raw)
In-Reply-To: <df6510fe-1dfd-1585-8590-db230c71d367@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>
Signed-off-by: Volker Rümelin <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.35.3
next prev parent reply other threads:[~2023-02-06 18:55 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-06 18:47 [PATCH v2 00/17] audio: improve callback interface for audio frontends Volker Rümelin
2023-02-06 18:52 ` [PATCH v2 01/17] audio: change type of mix_buf and conv_buf Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 02/17] audio: change type and name of the resample buffer Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 03/17] audio: make the resampling code greedy Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` Volker Rümelin [this message]
2023-02-22 10:49 ` [PATCH v2 04/17] audio: replace the resampling loop in audio_pcm_sw_write() Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 05/17] audio: remove sw == NULL check Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 06/17] audio: rename variables in audio_pcm_sw_write() Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 07/17] audio: don't misuse audio_pcm_sw_write() Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 08/17] audio: remove unused noop_conv() function Volker Rümelin
2023-02-22 10:49 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 09/17] audio/mixeng: calculate number of input frames Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 10/17] audio: wire up st_rate_frames_in() Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 11/17] audio: replace the resampling loop in audio_pcm_sw_read() Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 12/17] audio: rename variables " Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 13/17] audio/mixeng: calculate number of output frames Volker Rümelin
2023-02-06 18:52 ` [PATCH v2 14/17] audio: wire up st_rate_frames_out() Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 15/17] audio: handle leftover audio frame from upsampling Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 16/17] audio/audio_template: substitute sw->hw with hw Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
2023-02-06 18:52 ` [PATCH v2 17/17] audio: remove sw->ratio Volker Rümelin
2023-02-22 10:50 ` Marc-André Lureau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230206185237.8358-4-vr_qemu@t-online.de \
--to=vr_qemu@t-online.de \
--cc=kraxel@redhat.com \
--cc=marcandre.lureau@gmail.com \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=qemu-devel@nongnu.org \
--cc=qemu_oss@crudebyte.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).