aboutsummaryrefslogtreecommitdiff
path: root/audio/mixeng.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/mixeng.c')
-rw-r--r--audio/mixeng.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/audio/mixeng.c b/audio/mixeng.c
index fe454e0725..a24c8c45a7 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -440,6 +440,45 @@ 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
+ *
+ * When downsampling, there may be more than one correct result. In this
+ * case, the function returns the maximum number of input frames needed.
+ */
+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));