diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2014-10-12 21:52:28 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2014-10-12 21:52:28 +0000 |
commit | eb3a60751d717adceb4ef55587ae1a28df9222f5 (patch) | |
tree | 6d17c48498ca806aa43ca4978241b235f32efd5a | |
parent | 4e733227bf0d961124141a2575b5116939cf749b (diff) |
Don't assume that right-shift sign-extends integers.
-rw-r--r-- | usr.bin/sndiod/dsp.c | 48 | ||||
-rw-r--r-- | usr.bin/sndiod/dsp.h | 4 |
2 files changed, 33 insertions, 19 deletions
diff --git a/usr.bin/sndiod/dsp.c b/usr.bin/sndiod/dsp.c index f7c186bc362..1403230f38e 100644 --- a/usr.bin/sndiod/dsp.c +++ b/usr.bin/sndiod/dsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsp.c,v 1.7 2014/08/13 08:42:46 nicm Exp $ */ +/* $OpenBSD: dsp.c,v 1.8 2014/10/12 21:52:27 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> * @@ -328,9 +328,9 @@ enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) { unsigned int f; adata_t *idata; - int s; + unsigned int s; unsigned int oshift; - int osigbit; + unsigned int obias; unsigned int obps; unsigned int i; unsigned char *odata; @@ -352,7 +352,7 @@ enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) idata = (adata_t *)in; odata = out; oshift = p->shift; - osigbit = p->sigbit; + obias = p->bias; obps = p->bps; obnext = p->bnext; osnext = p->snext; @@ -362,10 +362,14 @@ enc_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) */ odata += p->bfirst; for (f = todo * p->nch; f > 0; f--) { - s = *idata++; + /* convert adata to u32 */ + s = (int)*idata++ + ADATA_UNIT; s <<= 32 - ADATA_BITS; + /* convert u32 to uN */ s >>= oshift; - s ^= osigbit; + /* convert uN to sN */ + s -= obias; + /* packetize sN */ for (i = obps; i > 0; i--) { *odata = (unsigned char)s; s >>= 8; @@ -382,8 +386,9 @@ void enc_sil_do(struct conv *p, unsigned char *out, int todo) { unsigned int f; - int s; - int osigbit; + unsigned int s; + unsigned int oshift; + int obias; unsigned int obps; unsigned int i; unsigned char *odata; @@ -403,7 +408,8 @@ enc_sil_do(struct conv *p, unsigned char *out, int todo) * order local variables more "cache-friendly". */ odata = out; - osigbit = p->sigbit; + oshift = p->shift; + obias = p->bias; obps = p->bps; obnext = p->bnext; osnext = p->snext; @@ -413,7 +419,7 @@ enc_sil_do(struct conv *p, unsigned char *out, int todo) */ odata += p->bfirst; for (f = todo * p->nch; f > 0; f--) { - s = osigbit; + s = ((1U << 31) >> oshift) - obias; for (i = obps; i > 0; i--) { *odata = (unsigned char)s; s >>= 8; @@ -431,12 +437,16 @@ enc_init(struct conv *p, struct aparams *par, int nch) { p->nch = nch; p->bps = par->bps; - p->sigbit = par->sig ? 0 : 1 << (par->bits - 1); if (par->msb) { p->shift = 32 - par->bps * 8; } else { p->shift = 32 - par->bits; } + if (par->sig) { + p->bias = (1U << 31) >> p->shift; + } else { + p->bias = 0; + } if (!par->le) { p->bfirst = par->bps - 1; p->bnext = -1; @@ -466,11 +476,11 @@ dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) unsigned int f; unsigned int ibps; unsigned int i; - int s = 0xdeadbeef; + unsigned int s = 0xdeadbeef; unsigned char *idata; int ibnext; int isnext; - int isigbit; + unsigned int ibias; unsigned int ishift; adata_t *odata; @@ -490,7 +500,7 @@ dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) odata = (adata_t *)out; ibps = p->bps; ibnext = p->bnext; - isigbit = p->sigbit; + ibias = p->bias; ishift = p->shift; isnext = p->snext; @@ -505,10 +515,10 @@ dec_do(struct conv *p, unsigned char *in, unsigned char *out, int todo) idata += ibnext; } idata += isnext; - s ^= isigbit; + s += ibias; s <<= ishift; s >>= 32 - ADATA_BITS; - *odata++ = s; + *odata++ = s - ADATA_UNIT; } } @@ -519,13 +529,17 @@ void dec_init(struct conv *p, struct aparams *par, int nch) { p->bps = par->bps; - p->sigbit = par->sig ? 0 : 1 << (par->bits - 1); p->nch = nch; if (par->msb) { p->shift = 32 - par->bps * 8; } else { p->shift = 32 - par->bits; } + if (par->sig) { + p->bias = (1U << 31) >> p->shift; + } else { + p->bias = 0; + } if (par->le) { p->bfirst = par->bps - 1; p->bnext = -1; diff --git a/usr.bin/sndiod/dsp.h b/usr.bin/sndiod/dsp.h index 8b5bb2e4844..93f06566786 100644 --- a/usr.bin/sndiod/dsp.h +++ b/usr.bin/sndiod/dsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dsp.h,v 1.3 2014/03/05 20:06:05 ratchov Exp $ */ +/* $OpenBSD: dsp.h,v 1.4 2014/10/12 21:52:27 ratchov Exp $ */ /* * Copyright (c) 2012 Alexandre Ratchov <alex@caoua.org> * @@ -124,7 +124,7 @@ struct conv { int bfirst; /* bytes to skip at startup */ unsigned int bps; /* bytes per sample */ unsigned int shift; /* shift to get 32bit MSB */ - int sigbit; /* sign bits to XOR */ + unsigned int bias; /* bias of unsigned samples */ int bnext; /* to reach the next byte */ int snext; /* to reach the next sample */ int nch; |