diff options
| author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-14 17:16:50 +0100 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-12-14 17:16:50 +0100 |
| commit | 1fdd311f2faa15b9335be02f6bd81716965e968a (patch) | |
| tree | b4e883aa92b3a884a818a23ca1438eb05350486e | |
| parent | 776f3726dd6f2401fa1b25163b2139ae9ac84115 (diff) | |
| download | plan9front-1fdd311f2faa15b9335be02f6bd81716965e968a.tar.xz | |
audio/pcmconv: implement stereo -> mono conversion (mixing)
| -rw-r--r-- | sys/src/cmd/audio/pcmconv/pcmconv.c | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/sys/src/cmd/audio/pcmconv/pcmconv.c b/sys/src/cmd/audio/pcmconv/pcmconv.c index 09851da93..a50814abc 100644 --- a/sys/src/cmd/audio/pcmconv/pcmconv.c +++ b/sys/src/cmd/audio/pcmconv/pcmconv.c @@ -41,6 +41,19 @@ enum { One = 1<<Np, }; +#define MAXINT ((int)(~0UL>>1)) +#define MININT (MAXINT+1) + +int +clip(vlong v) +{ + if(v > MAXINT) + return MAXINT; + if(v < MININT) + return MININT; + return v; +} + int chaninit(Chan *c, int irate, int orate, int count) { @@ -132,13 +145,7 @@ filter(Chan *c) v *= c->u; v >>= 27; - /* clipping */ - if(v > 0x7fffffffLL) - return 0x7fffffff; - if(v < -0x80000000LL) - return -0x80000000; - - return v; + return clip(v); } int* @@ -212,6 +219,15 @@ dither(int *y, int ibits, int obits, int count) } void +mixin(int *y, int *x, int count) +{ + while(count--){ + *y = clip((vlong)*y + *x++); + y++; + } +} + +void siconv(int *dst, uchar *src, int bits, int skip, int count) { int i, v, s, b; @@ -322,11 +338,11 @@ ficonv(int *dst, uchar *src, int bits, int skip, int count) f = *((float*)src), src += skip; if(f > 1.0) - *dst++ = 0x7fffffff; + *dst++ = MAXINT; else if(f < -1.0) - *dst++ = -0x80000000; + *dst++ = MININT; else - *dst++ = f*2147483647.f; + *dst++ = f*((float)MAXINT); } } else { while(count--){ @@ -334,11 +350,11 @@ ficonv(int *dst, uchar *src, int bits, int skip, int count) d = *((double*)src), src += skip; if(d > 1.0) - *dst++ = 0x7fffffff; + *dst++ = MAXINT; else if(d < -1.0) - *dst++ = -0x80000000; + *dst++ = MININT; else - *dst++ = d*2147483647.f; + *dst++ = d*((float)MAXINT); } } } @@ -489,12 +505,12 @@ foconv(int *src, uchar *dst, int bits, int skip, int count) { if(bits == 32){ while(count--){ - *((float*)dst) = *src++ / 2147483647.f; + *((float*)dst) = *src++ / ((float)MAXINT); dst += skip; } } else { while(count--){ - *((double*)dst) = *src++ / 2147483647.f; + *((double*)dst) = *src++ / ((double)MAXINT); dst += skip; } } @@ -662,7 +678,8 @@ main(int argc, char *argv[]) for(k=0; k < i.channels; k++) nout = chaninit(&ch[k], i.rate, o.rate, nin); - out = sbrk(sizeof(int) * nout); + /* out is also used for mixing before resampling, so needs to be max(nin, nout) */ + out = sbrk(sizeof(int) * (nout>nin? nout: nin)); obuf = sbrk(o.framesz * nout); for(;;){ @@ -676,6 +693,12 @@ main(int argc, char *argv[]) l -= n; n /= i.framesz; (*iconv)(in, ibuf, i.bits, i.framesz, n); + if(i.channels > o.channels){ + for(k=1; k<i.channels; k++){ + (*iconv)(out, ibuf + k*((i.bits+7)/8), i.bits, i.framesz, n); + mixin(in, out, n); + } + } dither(in, i.abits, o.abits, n); m = resample(&ch[0], in, out, n) - out; if(m < 1){ |
