version 1.15, 2008/11/04 14:16:09 |
version 1.16, 2008/11/04 15:22:40 |
|
|
conv_bcopy(struct aconv *ist, struct aconv *ost, |
conv_bcopy(struct aconv *ist, struct aconv *ost, |
struct abuf *ibuf, struct abuf *obuf) |
struct abuf *ibuf, struct abuf *obuf) |
{ |
{ |
int *ictx; |
|
unsigned inch, ibps; |
unsigned inch, ibps; |
unsigned char *idata; |
unsigned char *idata; |
int ibnext, isigbit; |
int ibnext, isigbit; |
unsigned ishift; |
unsigned ishift; |
int isnext; |
int isnext; |
unsigned ipos, orate; |
|
unsigned ifr; |
|
int *octx; |
|
unsigned onch, oshift; |
unsigned onch, oshift; |
int osigbit; |
int osigbit; |
unsigned obps; |
unsigned obps; |
unsigned char *odata; |
unsigned char *odata; |
int obnext, osnext; |
int obnext, osnext; |
unsigned opos, irate; |
unsigned c, i, f; |
unsigned ofr; |
int ctxbuf[NCHAN_MAX], *ctx, s; |
unsigned c, i; |
unsigned icount, ocount, scount; |
int s, *ctx; |
|
unsigned icount, ocount; |
|
|
|
/* |
/* |
* It's ok to have s uninitialized, but we dont want the compiler to |
* It's ok to have s uninitialized, but we dont want the compiler to |
|
|
* Calculate max frames readable at once from the input buffer. |
* Calculate max frames readable at once from the input buffer. |
*/ |
*/ |
idata = abuf_rgetblk(ibuf, &icount, 0); |
idata = abuf_rgetblk(ibuf, &icount, 0); |
ifr = icount / ibuf->bpf; |
icount /= ibuf->bpf; |
icount = ifr * ibuf->bpf; |
if (icount == 0) |
|
return; |
odata = abuf_wgetblk(obuf, &ocount, 0); |
odata = abuf_wgetblk(obuf, &ocount, 0); |
ofr = ocount / obuf->bpf; |
ocount /= obuf->bpf; |
ocount = ofr * obuf->bpf; |
if (ocount == 0) |
|
return; |
|
scount = (icount < ocount) ? icount : ocount; |
|
DPRINTFN(4, "conv_bcopy: scount=%u\n", scount); |
|
|
/* |
/* |
* Partially copy structures into local variables, to avoid |
* Partially copy structures into local variables, to avoid |
* unnecessary indirections; this also allows the compiler to |
* unnecessary indirections; this also allows the compiler to |
* order local variables more "cache-friendly". |
* order local variables more "cache-friendly". |
*/ |
*/ |
ictx = ist->ctx + ist->cmin; |
|
octx = ist->ctx + ost->cmin; |
|
inch = ist->nch; |
inch = ist->nch; |
ibps = ist->bps; |
ibps = ist->bps; |
ibnext = ist->bnext; |
ibnext = ist->bnext; |
isigbit = ist->sigbit; |
isigbit = ist->sigbit; |
ishift = ist->shift; |
ishift = ist->shift; |
isnext = ist->snext; |
isnext = ist->snext; |
ipos = ist->pos; |
|
irate = ist->rate; |
|
onch = ost->nch; |
onch = ost->nch; |
oshift = ost->shift; |
oshift = ost->shift; |
osigbit = ost->sigbit; |
osigbit = ost->sigbit; |
obps = ost->bps; |
obps = ost->bps; |
obnext = ost->bnext; |
obnext = ost->bnext; |
osnext = ost->snext; |
osnext = ost->snext; |
opos = ost->pos; |
|
orate = ost->rate; |
|
|
|
/* |
/* |
* Start conversion. |
* Start conversion. |
*/ |
*/ |
idata += ist->bfirst; |
idata += ist->bfirst; |
odata += ost->bfirst; |
odata += ost->bfirst; |
DPRINTFN(4, "conv_bcopy: ifr=%d ofr=%d\n", ifr, ofr); |
for (f = scount; f > 0; f--) { |
for (;;) { |
ctx = ctxbuf; |
if ((int)(ipos - opos) > 0) { |
for (c = inch; c > 0; c--) { |
if (ofr == 0) |
for (i = ibps; i > 0; i--) { |
break; |
s <<= 8; |
ctx = octx; |
s |= *idata; |
for (c = onch; c > 0; c--) { |
idata += ibnext; |
s = *ctx++ << 16; |
|
s >>= oshift; |
|
s ^= osigbit; |
|
for (i = obps; i > 0; i--) { |
|
*odata = (unsigned char)s; |
|
s >>= 8; |
|
odata += obnext; |
|
} |
|
odata += osnext; |
|
} |
} |
opos += irate; |
s ^= isigbit; |
ofr--; |
s <<= ishift; |
} else { |
*ctx++ = (short)(s >> 16); |
if (ifr == 0) |
idata += isnext; |
break; |
} |
ctx = ictx; |
ctx = ctxbuf; |
for (c = inch; c > 0; c--) { |
for (c = onch; c > 0; c--) { |
for (i = ibps; i > 0; i--) { |
s = *ctx++ << 16; |
s <<= 8; |
s >>= oshift; |
s |= *idata; |
s ^= osigbit; |
idata += ibnext; |
for (i = obps; i > 0; i--) { |
} |
*odata = (unsigned char)s; |
s ^= isigbit; |
s >>= 8; |
s <<= ishift; |
odata += obnext; |
*ctx++ = (short)(s >> 16); |
|
idata += isnext; |
|
} |
} |
ipos += orate; |
odata += osnext; |
ifr--; |
|
} |
} |
} |
} |
ist->pos = ipos; |
|
ost->pos = opos; |
|
DPRINTFN(4, "conv_bcopy: done, ifr=%d ofr=%d\n", ifr, ofr); |
|
|
|
/* |
/* |
* Update FIFO pointers. |
* Update FIFO pointers. |
*/ |
*/ |
icount -= ifr * ist->bpf; |
abuf_rdiscard(ibuf, scount * ibuf->bpf); |
ocount -= ofr * ost->bpf; |
abuf_wcommit(obuf, scount * obuf->bpf); |
abuf_rdiscard(ibuf, icount); |
|
abuf_wcommit(obuf, ocount); |
|
} |
} |
|
|
int |
int |
|
|
void |
void |
aconv_init(struct aconv *st, struct aparams *par, int input) |
aconv_init(struct aconv *st, struct aparams *par, int input) |
{ |
{ |
unsigned i; |
|
|
|
st->bps = par->bps; |
st->bps = par->bps; |
st->sigbit = par->sig ? 0 : 1 << (par->bits - 1); |
st->sigbit = par->sig ? 0 : 1 << (par->bits - 1); |
if (par->msb) { |
if (par->msb) { |
|
|
st->cmin = par->cmin; |
st->cmin = par->cmin; |
st->nch = par->cmax - par->cmin + 1; |
st->nch = par->cmax - par->cmin + 1; |
st->bpf = st->nch * st->bps; |
st->bpf = st->nch * st->bps; |
st->rate = par->rate; |
|
st->pos = 0; |
|
|
|
for (i = 0; i < NCHAN_MAX; i++) |
|
st->ctx[i] = 0; |
|
} |
} |
|
|
void |
|
conv_ipos(struct aproc *p, struct abuf *ibuf, int delta) |
|
{ |
|
struct abuf *obuf = LIST_FIRST(&p->obuflist); |
|
long long ipos; |
|
int ifac, ofac; |
|
|
|
DPRINTFN(3, "conv_ipos: %d\n", delta); |
|
|
|
ifac = p->u.conv.ist.rate; |
|
ofac = p->u.conv.ost.rate; |
|
ipos = p->u.conv.idelta + (long long)delta * ofac; |
|
delta = (ipos + ifac - 1) / ifac; |
|
p->u.conv.idelta = ipos - (long long)delta * ifac; |
|
abuf_ipos(obuf, delta); |
|
} |
|
|
|
void |
|
conv_opos(struct aproc *p, struct abuf *obuf, int delta) |
|
{ |
|
struct abuf *ibuf = LIST_FIRST(&p->ibuflist); |
|
long long opos; |
|
int ifac, ofac; |
|
|
|
DPRINTFN(3, "conv_opos: %d\n", delta); |
|
|
|
ifac = p->u.conv.ist.rate; |
|
ofac = p->u.conv.ost.rate; |
|
opos = p->u.conv.odelta + (long long)delta * ifac; |
|
delta = (opos + ofac - 1) / ofac; |
|
p->u.conv.odelta = opos - (long long)delta * ofac; |
|
abuf_opos(ibuf, delta); |
|
} |
|
|
|
struct aproc_ops conv_ops = { |
struct aproc_ops conv_ops = { |
"conv", |
"conv", |
conv_in, |
conv_in, |
|
|
conv_hup, |
conv_hup, |
NULL, |
NULL, |
NULL, |
NULL, |
conv_ipos, |
NULL, /* ipos */ |
conv_opos, |
NULL, /* opos */ |
NULL |
NULL |
}; |
}; |
|
|
|
|
resamp_new(char *name, struct aparams *ipar, struct aparams *opar) |
resamp_new(char *name, struct aparams *ipar, struct aparams *opar) |
{ |
{ |
struct aproc *p; |
struct aproc *p; |
|
unsigned i; |
|
|
p = aproc_new(&resamp_ops, name); |
p = aproc_new(&resamp_ops, name); |
p->u.resamp.irate = ipar->rate; |
p->u.resamp.irate = ipar->rate; |
|
|
p->u.resamp.opos = 0; |
p->u.resamp.opos = 0; |
p->u.resamp.idelta = 0; |
p->u.resamp.idelta = 0; |
p->u.resamp.odelta = 0; |
p->u.resamp.odelta = 0; |
|
for (i = 0; i < NCHAN_MAX; i++) |
|
p->u.resamp.ctx[i] = 0; |
if (debug_level > 0) { |
if (debug_level > 0) { |
DPRINTF("resamp_new: %s: ", p->name); |
DPRINTF("resamp_new: %s: ", p->name); |
aparams_print2(ipar, opar); |
aparams_print2(ipar, opar); |