ref: 58fcee35d18a20914e3a23b768ade28306fc8483
parent: a685f57d24f00cb6eea3a0b9e9479b9b8be048f7
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Dec 14 12:16:50 EST 2012
audio/pcmconv: implement stereo -> mono conversion (mixing)
--- a/sys/src/cmd/audio/pcmconv/pcmconv.c
+++ b/sys/src/cmd/audio/pcmconv/pcmconv.c
@@ -41,7 +41,20 @@
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)
{ static int h[] = {@@ -132,13 +145,7 @@
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 @@
}
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 @@
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 @@
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 @@
{ 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 @@
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 @@
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){--
⑨