Message ID | 20230206185237.8358-9-vr_qemu@t-online.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | audio: improve callback interface for audio frontends | expand |
Hi On Mon, Feb 6, 2023 at 10:52 PM Volker Rümelin <vr_qemu@t-online.de> wrote: > > Calculate the exact number of audio input frames needed to get > a given number of audio output frames. The exact number of > frames depends only on the difference of opos - ipos and the > number of output frames. When downsampling, this function > returns the maximum number of input frames needed. > > This function will later replace the audio_frontend_frames_out() > function, which calculates the average number of input frames > rounded down to the nearest integer. > > Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> > Signed-off-by: Volker Rümelin <vr_qemu@t-online.de> We usually introduce functions with their usage, but ok Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> > --- > audio/mixeng.c | 36 ++++++++++++++++++++++++++++++++++++ > audio/mixeng.h | 1 + > 2 files changed, 37 insertions(+) > > diff --git a/audio/mixeng.c b/audio/mixeng.c > index fe454e0725..6bb3d54f77 100644 > --- a/audio/mixeng.c > +++ b/audio/mixeng.c > @@ -440,6 +440,42 @@ void st_rate_stop (void *opaque) > g_free (opaque); > } > > +/** > + * st_rate_frames_in() - returns the number of frames needed to > + * get frames_out frames after resampling > + * > + * @opaque: pointer to struct rate > + * @frames_out: number of frames > + */ > +uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out) > +{ > + struct rate *rate = opaque; > + uint64_t opos_start, opos_end; > + uint32_t ipos_start, ipos_end; > + > + if (rate->opos_inc == 1ULL << 32) { > + return frames_out; > + } > + > + if (frames_out) { > + opos_start = rate->opos; > + ipos_start = rate->ipos; > + } else { > + uint64_t offset; > + > + /* add offset = ceil(opos_inc) to opos and ipos to avoid an underflow */ > + offset = (rate->opos_inc + (1ULL << 32) - 1) & ~((1ULL << 32) - 1); > + opos_start = rate->opos + offset; > + ipos_start = rate->ipos + (offset >> 32); > + } > + /* last frame written was at opos_start - rate->opos_inc */ > + opos_end = opos_start - rate->opos_inc + rate->opos_inc * frames_out; > + ipos_end = (opos_end >> 32) + 1; > + > + /* last frame read was at ipos_start - 1 */ > + return ipos_end + 1 > ipos_start ? ipos_end + 1 - ipos_start : 0; > +} > + > void mixeng_clear (struct st_sample *buf, int len) > { > memset (buf, 0, len * sizeof (struct st_sample)); > diff --git a/audio/mixeng.h b/audio/mixeng.h > index 2dcd6df245..64c1e231cc 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_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); > > -- > 2.35.3 > -- Marc-André Lureau
diff --git a/audio/mixeng.c b/audio/mixeng.c index fe454e0725..6bb3d54f77 100644 --- a/audio/mixeng.c +++ b/audio/mixeng.c @@ -440,6 +440,42 @@ void st_rate_stop (void *opaque) g_free (opaque); } +/** + * st_rate_frames_in() - returns the number of frames needed to + * get frames_out frames after resampling + * + * @opaque: pointer to struct rate + * @frames_out: number of frames + */ +uint32_t st_rate_frames_in(void *opaque, uint32_t frames_out) +{ + struct rate *rate = opaque; + uint64_t opos_start, opos_end; + uint32_t ipos_start, ipos_end; + + if (rate->opos_inc == 1ULL << 32) { + return frames_out; + } + + if (frames_out) { + opos_start = rate->opos; + ipos_start = rate->ipos; + } else { + uint64_t offset; + + /* add offset = ceil(opos_inc) to opos and ipos to avoid an underflow */ + offset = (rate->opos_inc + (1ULL << 32) - 1) & ~((1ULL << 32) - 1); + opos_start = rate->opos + offset; + ipos_start = rate->ipos + (offset >> 32); + } + /* last frame written was at opos_start - rate->opos_inc */ + opos_end = opos_start - rate->opos_inc + rate->opos_inc * frames_out; + ipos_end = (opos_end >> 32) + 1; + + /* last frame read was at ipos_start - 1 */ + return ipos_end + 1 > ipos_start ? ipos_end + 1 - ipos_start : 0; +} + void mixeng_clear (struct st_sample *buf, int len) { memset (buf, 0, len * sizeof (struct st_sample)); diff --git a/audio/mixeng.h b/audio/mixeng.h index 2dcd6df245..64c1e231cc 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_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);