From cf03f7423df934b28561316033bba4136c3f4724 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jun 2018 08:06:52 +0200 Subject: [PATCH 1/2] sndiod: move all conversions in dev_mix_badd() and dev_sub_bcopy() The conversion chain processes exactly one block, so no need to calculate & count the number of processed samples. This allows to move the calls to processing routines in dev_mix_badd() and dev_sub_bcopy(), which is much simpler. No behaviour change. --- sndiod/dev.c | 177 ++++++++++++++++++++++++--------------------------- 1 file changed, 83 insertions(+), 94 deletions(-) diff --git a/sndiod/dev.c b/sndiod/dev.c index 6a4cff8..d13ba28 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -46,12 +46,8 @@ void dev_midi_omsg(void *, unsigned char *, int); void dev_midi_fill(void *, int); void dev_midi_exit(void *); -int play_filt_resamp(struct slot *, void *, void *, int); -int play_filt_dec(struct slot *, void *, void *, int); void dev_mix_badd(struct dev *, struct slot *); void dev_mix_adjvol(struct dev *); -int rec_filt_resamp(struct slot *, void *, void *, int); -int rec_filt_enc(struct slot *, void *, void *, int); void dev_sub_bcopy(struct dev *, struct slot *); void dev_onmove(struct dev *, int); @@ -553,56 +549,14 @@ slot_skip(struct slot *s) return max - s->skip; } -int -play_filt_resamp(struct slot *s, void *res_in, void *out, int todo) -{ - int i, offs, vol, nch; - void *in; - - if (s->mix.resampbuf) { - todo = resamp_do(&s->mix.resamp, - res_in, s->mix.resampbuf, todo); - in = s->mix.resampbuf; - } else - in = res_in; - - nch = s->mix.cmap.nch; - vol = ADATA_MUL(s->mix.weight, s->mix.vol) / s->mix.join; - cmap_add(&s->mix.cmap, in, out, vol, todo); - - offs = 0; - for (i = s->mix.join - 1; i > 0; i--) { - offs += nch; - cmap_add(&s->mix.cmap, (adata_t *)in + offs, out, vol, todo); - } - offs = 0; - for (i = s->mix.expand - 1; i > 0; i--) { - offs += nch; - cmap_add(&s->mix.cmap, in, (adata_t *)out + offs, vol, todo); - } - return todo; -} - -int -play_filt_dec(struct slot *s, void *in, void *out, int todo) -{ - void *tmp; - - tmp = s->mix.decbuf; - if (tmp) - dec_do(&s->mix.dec, in, tmp, todo); - return play_filt_resamp(s, tmp ? tmp : in, out, todo); -} - /* - * mix "todo" frames from the input block over the output block; if - * there are frames to drop, less frames are consumed from the input + * Mix the slot input block over the output block */ void dev_mix_badd(struct dev *d, struct slot *s) { - adata_t *idata, *odata; - int icount; + adata_t *idata, *odata, *in; + int icount, i, offs, vol, nch; odata = DEV_PBUF(d); idata = (adata_t *)abuf_rgetblk(&s->mix.buf, &icount); @@ -615,7 +569,43 @@ dev_mix_badd(struct dev *d, struct slot *s) panic(); } #endif - play_filt_dec(s, idata, odata, s->round); + + /* + * Apply the following processing chain: + * + * dec -> resamp-> cmap + * + * where the first two are optional. + */ + + in = idata; + + if (s->mix.decbuf) { + dec_do(&s->mix.dec, (void *)in, s->mix.decbuf, s->round); + in = s->mix.decbuf; + } + + if (s->mix.resampbuf) { + resamp_do(&s->mix.resamp, in, s->mix.resampbuf, s->round); + in = s->mix.resampbuf; + } + + nch = s->mix.cmap.nch; + vol = ADATA_MUL(s->mix.weight, s->mix.vol) / s->mix.join; + cmap_add(&s->mix.cmap, in, odata, vol, d->round); + + offs = 0; + for (i = s->mix.join - 1; i > 0; i--) { + offs += nch; + cmap_add(&s->mix.cmap, in + offs, odata, vol, d->round); + } + + offs = 0; + for (i = s->mix.expand - 1; i > 0; i--) { + offs += nch; + cmap_add(&s->mix.cmap, in, odata + offs, vol, d->round); + } + abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf); } @@ -664,56 +654,19 @@ dev_mix_adjvol(struct dev *d) } } -int -rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo) -{ - int i, vol, offs, nch; - void *out = res_out; - - out = (s->sub.resampbuf) ? s->sub.resampbuf : res_out; - - nch = s->sub.cmap.nch; - vol = ADATA_UNIT / s->sub.join; - cmap_copy(&s->sub.cmap, in, out, vol, todo); - - offs = 0; - for (i = s->sub.join - 1; i > 0; i--) { - offs += nch; - cmap_add(&s->sub.cmap, (adata_t *)in + offs, out, vol, todo); - } - offs = 0; - for (i = s->sub.expand - 1; i > 0; i--) { - offs += nch; - cmap_copy(&s->sub.cmap, in, (adata_t *)out + offs, vol, todo); - } - if (s->sub.resampbuf) { - todo = resamp_do(&s->sub.resamp, - s->sub.resampbuf, res_out, todo); - } - return todo; -} - -int -rec_filt_enc(struct slot *s, void *in, void *out, int todo) -{ - void *tmp; - - tmp = s->sub.encbuf; - todo = rec_filt_resamp(s, in, tmp ? tmp : out, todo); - if (tmp) - enc_do(&s->sub.enc, tmp, out, todo); - return todo; -} - /* * Copy data from slot to device */ void dev_sub_bcopy(struct dev *d, struct slot *s) { - adata_t *idata, *odata; + adata_t *idata, *enc_out, *resamp_out, *cmap_out; + void *odata; int ocount, moffs; + int i, vol, offs, nch; + + if (s->mode & MODE_MON) { moffs = d->poffs + d->round; if (moffs == d->psize) @@ -728,8 +681,44 @@ dev_sub_bcopy(struct dev *d, struct slot *s) panic(); } #endif - ocount = rec_filt_enc(s, idata, odata, d->round); - abuf_wcommit(&s->sub.buf, ocount * s->sub.bpf); + + /* + * Apply the following processing chain: + * + * cmap -> resamp -> enc + * + * where the last two are optional. + */ + + enc_out = odata; + resamp_out = s->sub.encbuf ? s->sub.encbuf : enc_out; + cmap_out = s->sub.resampbuf ? s->sub.resampbuf : resamp_out; + + nch = s->sub.cmap.nch; + vol = ADATA_UNIT / s->sub.join; + cmap_copy(&s->sub.cmap, idata, cmap_out, vol, d->round); + + offs = 0; + for (i = s->sub.join - 1; i > 0; i--) { + offs += nch; + cmap_add(&s->sub.cmap, idata + offs, cmap_out, vol, d->round); + } + + offs = 0; + for (i = s->sub.expand - 1; i > 0; i--) { + offs += nch; + cmap_copy(&s->sub.cmap, idata, cmap_out + offs, vol, d->round); + } + + if (s->sub.resampbuf) { + resamp_do(&s->sub.resamp, + s->sub.resampbuf, resamp_out, d->round); + } + + if (s->sub.encbuf) + enc_do(&s->sub.enc, s->sub.encbuf, (void *)enc_out, s->round); + + abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf); } /* From 210da6b0cbfa39cb947b51f98515c068b7ef96c9 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Fri, 8 Jun 2018 08:16:30 +0200 Subject: [PATCH 2/2] sndiod: simplify the resampling routine --- sndiod/dsp.c | 68 ++++++++++++++-------------------------------------- sndiod/dsp.h | 3 +-- 2 files changed, 19 insertions(+), 52 deletions(-) diff --git a/sndiod/dsp.c b/sndiod/dsp.c index c2c6feb..3e80a2b 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -200,21 +200,26 @@ aparams_native(struct aparams *par) /* * resample the given number of frames */ -int +void resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) { unsigned int nch; adata_t *idata; unsigned int oblksz; - unsigned int ifr; int s, ds, diff; adata_t *odata; unsigned int iblksz; - unsigned int ofr; unsigned int c; adata_t *ctxbuf, *ctx; unsigned int ctx_start; +#ifdef DEBUG + if (todo % p->iblksz != 0) { + log_puts("resamp_do: partial blocks not supported\n"); + panic(); + } +#endif + /* * Partially copy structures into local variables, to avoid * unnecessary indirections; this also allows the compiler to @@ -222,30 +227,16 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) */ idata = in; odata = out; - diff = p->diff; + diff = p->oblksz; iblksz = p->iblksz; oblksz = p->oblksz; ctxbuf = p->ctx; ctx_start = p->ctx_start; nch = p->nch; - ifr = todo; - ofr = oblksz; - /* - * Start conversion. - */ -#ifdef DEBUG - if (log_level >= 4) { - log_puts("resamp: copying "); - log_puti(todo); - log_puts(" frames, diff = "); - log_putu(diff); - log_puts("\n"); - } -#endif for (;;) { - if (diff < 0) { - if (ifr == 0) + if (diff >= oblksz) { + if (todo == 0) break; ctx_start ^= 1; ctx = ctxbuf + ctx_start; @@ -253,43 +244,21 @@ resamp_do(struct resamp *p, adata_t *in, adata_t *out, int todo) *ctx = *idata++; ctx += RESAMP_NCTX; } - diff += oblksz; - ifr--; - } else if (diff > 0) { - if (ofr == 0) - break; + diff -= oblksz; + todo--; + } else { ctx = ctxbuf; for (c = nch; c > 0; c--) { - s = ctx[ctx_start]; - ds = ctx[ctx_start ^ 1] - s; + s = ctx[ctx_start ^ 1]; + ds = ctx[ctx_start] - s; ctx += RESAMP_NCTX; *odata++ = s + ADATA_MULDIV(ds, diff, oblksz); } - diff -= iblksz; - ofr--; - } else { - if (ifr == 0 || ofr == 0) - break; - ctx = ctxbuf + ctx_start; - for (c = nch; c > 0; c--) { - *odata++ = *ctx; - ctx += RESAMP_NCTX; - } - ctx_start ^= 1; - ctx = ctxbuf + ctx_start; - for (c = nch; c > 0; c--) { - *ctx = *idata++; - ctx += RESAMP_NCTX; - } - diff -= iblksz; - diff += oblksz; - ifr--; - ofr--; + diff += iblksz; } } - p->diff = diff; + p->ctx_start = ctx_start; - return oblksz - ofr; } /* @@ -303,7 +272,6 @@ resamp_init(struct resamp *p, unsigned int iblksz, p->iblksz = iblksz; p->oblksz = oblksz; - p->diff = 0; p->nch = nch; p->ctx_start = 0; for (i = 0; i < NCHAN_MAX * RESAMP_NCTX; i++) diff --git a/sndiod/dsp.h b/sndiod/dsp.h index 2344b65..0b5b86f 100644 --- a/sndiod/dsp.h +++ b/sndiod/dsp.h @@ -115,7 +115,6 @@ struct resamp { unsigned int ctx_start; adata_t ctx[NCHAN_MAX * RESAMP_NCTX]; unsigned int iblksz, oblksz; - int diff; int nch; }; @@ -146,7 +145,7 @@ int aparams_strtoenc(struct aparams *, char *); int aparams_enctostr(struct aparams *, char *); int aparams_native(struct aparams *); -int resamp_do(struct resamp *, adata_t *, adata_t *, int); +void resamp_do(struct resamp *, adata_t *, adata_t *, int); void resamp_init(struct resamp *, unsigned int, unsigned int, int); void enc_do(struct conv *, unsigned char *, unsigned char *, int); void enc_sil_do(struct conv *, unsigned char *, int);