From 00ffc8f5ab2f08705d4bea33f61ffeb256cc84ba Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Tue, 7 Jun 2016 08:11:46 +0200 Subject: [PATCH] Add resamp_getcnt() routine to calculate the exact number of samples that would be consumed and produced by the sampler rate converter. Use it to avoid partial samples that are not properly handled. Fixes last samples of certain files causing aucat to abort. --- aucat/aucat.c | 34 +++++++++++++------------------ aucat/dsp.c | 55 ++++++++++++++++++++++++++++++++------------------- aucat/dsp.h | 3 +-- 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/aucat/aucat.c b/aucat/aucat.c index caaf9a2..429c444 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -439,16 +439,18 @@ slot_del(struct slot *s) xfree(s); } -static int -slot_ocnt(struct slot *s, int icnt) +static void +slot_getcnt(struct slot *s, int *icnt, int *ocnt) { - return s->resampbuf ? resamp_ocnt(&s->resamp, icnt) : icnt; -} + int cnt; -static int -slot_icnt(struct slot *s, int ocnt) -{ - return s->resampbuf ? resamp_icnt(&s->resamp, ocnt) : ocnt; + if (s->resampbuf) + resamp_getcnt(&s->resamp, icnt, ocnt); + else { + cnt = (*icnt < *ocnt) ? *icnt : *ocnt; + *icnt = cnt; + *ocnt = cnt; + } } static void @@ -529,13 +531,9 @@ slot_mix_badd(struct slot *s, adata_t *odata) } while (otodo > 0) { idata = (adata_t *)abuf_rgetblk(&s->buf, &len); - icnt = len / s->bpf; - ocnt = slot_ocnt(s, icnt); - if (ocnt > otodo) { - ocnt = otodo; - icnt = slot_icnt(s, ocnt); - } + ocnt = otodo; + slot_getcnt(s, &icnt, &ocnt); if (icnt == 0) break; play_filt_dec(s, idata, odata, icnt, ocnt); @@ -607,13 +605,9 @@ slot_sub_bcopy(struct slot *s, adata_t *idata, int itodo) while (itodo > 0) { odata = (adata_t *)abuf_wgetblk(&s->buf, &len); - ocnt = len / s->bpf; - icnt = slot_icnt(s, ocnt); - if (icnt > itodo) { - icnt = itodo; - ocnt = slot_ocnt(s, icnt); - } + icnt = itodo; + slot_getcnt(s, &icnt, &ocnt); if (ocnt == 0) break; rec_filt_enc(s, idata, odata, icnt, ocnt); diff --git a/aucat/dsp.c b/aucat/dsp.c index b525632..034333c 100644 --- a/aucat/dsp.c +++ b/aucat/dsp.c @@ -268,35 +268,50 @@ aparams_native(struct aparams *par) } /* - * return the number of output frames resamp_do() would produce with - * the given number of input frames + * return the number of input and output frame that would + * be consumed */ -int -resamp_ocnt(struct resamp *p, int icnt) +void +resamp_getcnt(struct resamp *p, int *icnt, int *ocnt) { - return ((long long)p->oblksz * icnt + p->diff) / p->iblksz; -} + int diff, ifr, ofr; -/* - * return the number of input frames resamp_do() needs in order to - * produce the given number of output frames - */ -int -resamp_icnt(struct resamp *p, int ocnt) -{ - return ((long long)p->iblksz * ocnt - p->diff + - p->oblksz - 1) / p->oblksz; + diff = p->diff; + ifr = *icnt; + ofr = *ocnt; + + for (;;) { + if (diff < 0) { + if (ifr == 0) + break; + diff += p->oblksz; + ifr--; + } else if (diff > 0) { + if (ofr == 0) + break; + diff -= p->iblksz; + ofr--; + } else { + if (ifr == 0 || ofr == 0) + break; + diff -= p->iblksz; + diff += p->oblksz; + ifr--; + ofr--; + } + } + *icnt -= ifr; + *ocnt -= ofr; } /* * Resample the given number of frames. The number of output frames - * must match the coresponding number the input frames. Either - * use: + * must match the coresponding number the input frames. Either always + * use icnt and ocnt such that: * - * icnt * orate = ocnt * irate + * icnt * oblksz = ocnt * iblksz * - * or use resamp_icnt() or resamp_ocnt() to calculate the proper - * numbers. + * or use resamp_getcnt() to calculate the proper numbers. */ void resamp_do(struct resamp *p, adata_t *in, adata_t *out, int icnt, int ocnt) diff --git a/aucat/dsp.h b/aucat/dsp.h index 5a1df5e..fa07f42 100644 --- a/aucat/dsp.h +++ b/aucat/dsp.h @@ -147,8 +147,7 @@ int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); int aparams_native(struct aparams *); -int resamp_ocnt(struct resamp *, int); -int resamp_icnt(struct resamp *, int); +void resamp_getcnt(struct resamp *, int *, int *); void resamp_do(struct resamp *, adata_t *, adata_t *, int, int); void resamp_init(struct resamp *, unsigned int, unsigned int, int); void enc_do(struct conv *, unsigned char *, unsigned char *, int);