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.
This commit is contained in:
Alexandre Ratchov 2016-06-07 08:11:46 +02:00
parent 2562fa7eb4
commit 00ffc8f5ab
3 changed files with 50 additions and 42 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);