audio/pcmconv: implement stereo -> mono conversion (mixing)
This commit is contained in:
parent
776f3726dd
commit
1fdd311f2f
1 changed files with 39 additions and 16 deletions
|
@ -41,6 +41,19 @@ enum {
|
||||||
One = 1<<Np,
|
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
|
int
|
||||||
chaninit(Chan *c, int irate, int orate, int count)
|
chaninit(Chan *c, int irate, int orate, int count)
|
||||||
{
|
{
|
||||||
|
@ -132,13 +145,7 @@ filter(Chan *c)
|
||||||
v *= c->u;
|
v *= c->u;
|
||||||
v >>= 27;
|
v >>= 27;
|
||||||
|
|
||||||
/* clipping */
|
return clip(v);
|
||||||
if(v > 0x7fffffffLL)
|
|
||||||
return 0x7fffffff;
|
|
||||||
if(v < -0x80000000LL)
|
|
||||||
return -0x80000000;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int*
|
int*
|
||||||
|
@ -211,6 +218,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
|
void
|
||||||
siconv(int *dst, uchar *src, int bits, int skip, int count)
|
siconv(int *dst, uchar *src, int bits, int skip, int count)
|
||||||
{
|
{
|
||||||
|
@ -322,11 +338,11 @@ ficonv(int *dst, uchar *src, int bits, int skip, int count)
|
||||||
|
|
||||||
f = *((float*)src), src += skip;
|
f = *((float*)src), src += skip;
|
||||||
if(f > 1.0)
|
if(f > 1.0)
|
||||||
*dst++ = 0x7fffffff;
|
*dst++ = MAXINT;
|
||||||
else if(f < -1.0)
|
else if(f < -1.0)
|
||||||
*dst++ = -0x80000000;
|
*dst++ = MININT;
|
||||||
else
|
else
|
||||||
*dst++ = f*2147483647.f;
|
*dst++ = f*((float)MAXINT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while(count--){
|
while(count--){
|
||||||
|
@ -334,11 +350,11 @@ ficonv(int *dst, uchar *src, int bits, int skip, int count)
|
||||||
|
|
||||||
d = *((double*)src), src += skip;
|
d = *((double*)src), src += skip;
|
||||||
if(d > 1.0)
|
if(d > 1.0)
|
||||||
*dst++ = 0x7fffffff;
|
*dst++ = MAXINT;
|
||||||
else if(d < -1.0)
|
else if(d < -1.0)
|
||||||
*dst++ = -0x80000000;
|
*dst++ = MININT;
|
||||||
else
|
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){
|
if(bits == 32){
|
||||||
while(count--){
|
while(count--){
|
||||||
*((float*)dst) = *src++ / 2147483647.f;
|
*((float*)dst) = *src++ / ((float)MAXINT);
|
||||||
dst += skip;
|
dst += skip;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while(count--){
|
while(count--){
|
||||||
*((double*)dst) = *src++ / 2147483647.f;
|
*((double*)dst) = *src++ / ((double)MAXINT);
|
||||||
dst += skip;
|
dst += skip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,7 +678,8 @@ main(int argc, char *argv[])
|
||||||
for(k=0; k < i.channels; k++)
|
for(k=0; k < i.channels; k++)
|
||||||
nout = chaninit(&ch[k], i.rate, o.rate, nin);
|
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);
|
obuf = sbrk(o.framesz * nout);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
|
@ -676,6 +693,12 @@ main(int argc, char *argv[])
|
||||||
l -= n;
|
l -= n;
|
||||||
n /= i.framesz;
|
n /= i.framesz;
|
||||||
(*iconv)(in, ibuf, i.bits, i.framesz, n);
|
(*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);
|
dither(in, i.abits, o.abits, n);
|
||||||
m = resample(&ch[0], in, out, n) - out;
|
m = resample(&ch[0], in, out, n) - out;
|
||||||
if(m < 1){
|
if(m < 1){
|
||||||
|
|
Loading…
Reference in a new issue