[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 24/27] audio: make recording packet length calculation exact
From: |
marcandre . lureau |
Subject: |
[PULL 24/27] audio: make recording packet length calculation exact |
Date: |
Mon, 6 Mar 2023 10:51:59 +0400 |
From: Volker RĂ¼melin <vr_qemu@t-online.de>
Introduce the new function st_rate_frames_out() to calculate the
exact number of audio output frames the resampling code can
generate from a given number of audio input frames. When upsampling,
this function returns the maximum number of output frames.
This new function replaces the audio_frontend_frames_in()
function, which calculated the average number of output frames
rounded down to the nearest integer. The audio_frontend_frames_in()
function was additionally used to limit the number of output frames
to the resample buffer size. In audio_pcm_sw_read() the variable
resample_buf.size replaces the open coded audio_frontend_frames_in()
function. In audio_run_in() an additional MIN() function is
necessary.
After this patch the audio packet length calculation for audio
recording is exact.
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Volker RĂ¼melin <vr_qemu@t-online.de>
Message-Id: <20230224190555.7409-12-vr_qemu@t-online.de>
---
audio/mixeng.h | 1 +
audio/audio.c | 29 ++++++++---------------------
audio/mixeng.c | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 21 deletions(-)
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 64c1e231cc..f9de7cffeb 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -52,6 +52,7 @@ void st_rate_flow(void *opaque, st_sample *ibuf, st_sample
*obuf,
void st_rate_flow_mix(void *opaque, st_sample *ibuf, st_sample *obuf,
size_t *isamp, size_t *osamp);
void st_rate_stop (void *opaque);
+uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in);
uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out);
void mixeng_clear (struct st_sample *buf, int len);
void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
diff --git a/audio/audio.c b/audio/audio.c
index 22c36d6660..dad17e59b8 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -579,7 +579,7 @@ static void audio_pcm_sw_resample_in(SWVoiceIn *sw,
static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t buf_len)
{
HWVoiceIn *hw = sw->hw;
- size_t live, frames_out_max, swlim, total_in, total_out;
+ size_t live, frames_out_max, total_in, total_out;
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
if (!live) {
@@ -590,12 +590,10 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf,
size_t buf_len)
return 0;
}
- frames_out_max = buf_len / sw->info.bytes_per_frame;
+ frames_out_max = MIN(buf_len / sw->info.bytes_per_frame,
+ sw->resample_buf.size);
- swlim = (live * sw->ratio) >> 32;
- swlim = MIN(swlim, frames_out_max);
-
- audio_pcm_sw_resample_in(sw, live, swlim, &total_in, &total_out);
+ audio_pcm_sw_resample_in(sw, live, frames_out_max, &total_in, &total_out);
if (!hw->pcm_ops->volume_in) {
mixeng_volume(sw->resample_buf.buffer, total_out, &sw->vol);
@@ -979,18 +977,6 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
}
}
-/**
- * audio_frontend_frames_in() - returns the number of frames the resampling
- * code generates from frames_in frames
- *
- * @sw: audio recording frontend
- * @frames_in: number of frames
- */
-static size_t audio_frontend_frames_in(SWVoiceIn *sw, size_t frames_in)
-{
- return (int64_t)frames_in * sw->ratio >> 32;
-}
-
static size_t audio_get_avail (SWVoiceIn *sw)
{
size_t live;
@@ -1007,9 +993,9 @@ static size_t audio_get_avail (SWVoiceIn *sw)
}
ldebug (
- "%s: get_avail live %zu frontend frames %zu\n",
+ "%s: get_avail live %zu frontend frames %u\n",
SW_NAME (sw),
- live, audio_frontend_frames_in(sw, live)
+ live, st_rate_frames_out(sw->rate, live)
);
return live;
@@ -1314,8 +1300,9 @@ static void audio_run_in (AudioState *s)
size_t sw_avail = audio_get_avail(sw);
size_t avail;
- avail = audio_frontend_frames_in(sw, sw_avail);
+ avail = st_rate_frames_out(sw->rate, sw_avail);
if (avail > 0) {
+ avail = MIN(avail, sw->resample_buf.size);
sw->callback.fn(sw->callback.opaque,
avail * sw->info.bytes_per_frame);
}
diff --git a/audio/mixeng.c b/audio/mixeng.c
index a24c8c45a7..69f6549224 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -440,6 +440,47 @@ void st_rate_stop (void *opaque)
g_free (opaque);
}
+/**
+ * st_rate_frames_out() - returns the number of frames the resampling code
+ * generates from frames_in frames
+ *
+ * @opaque: pointer to struct rate
+ * @frames_in: number of frames
+ *
+ * When upsampling, there may be more than one correct result. In this case,
+ * the function returns the maximum number of output frames the resampling
+ * code can generate.
+ */
+uint32_t st_rate_frames_out(void *opaque, uint32_t frames_in)
+{
+ struct rate *rate = opaque;
+ uint64_t opos_end, opos_delta;
+ uint32_t ipos_end;
+ uint32_t frames_out;
+
+ if (rate->opos_inc == 1ULL << 32) {
+ return frames_in;
+ }
+
+ /* no output frame without at least one input frame */
+ if (!frames_in) {
+ return 0;
+ }
+
+ /* last frame read was at rate->ipos - 1 */
+ ipos_end = rate->ipos - 1 + frames_in;
+ opos_end = (uint64_t)ipos_end << 32;
+
+ /* last frame written was at rate->opos - rate->opos_inc */
+ if (opos_end + rate->opos_inc <= rate->opos) {
+ return 0;
+ }
+ opos_delta = opos_end - rate->opos + rate->opos_inc;
+ frames_out = opos_delta / rate->opos_inc;
+
+ return opos_delta % rate->opos_inc ? frames_out : frames_out - 1;
+}
+
/**
* st_rate_frames_in() - returns the number of frames needed to
* get frames_out frames after resampling
--
2.39.2
- [PULL 14/27] audio: change type and name of the resample buffer, (continued)
- [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, 2023/03/06
- [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 <=
- [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
- [PULL 27/27] audio: remove sw->ratio, marcandre . lureau, 2023/03/06
- Re: [PULL 00/27] Audio patches, Peter Maydell, 2023/03/06