738 lines · 12.5 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <pcm.h> typedef struct Chan Chan;typedef struct Pcmconv Pcmconv; struct Chan{	ulong	ρ;	/* factor */ 	ulong	t;	/* time */ 	ulong	tΔ;	/* output step */	ulong	lΔ;	/* filter step */	ulong	le;	/* filter end */ 	int	u;	/* unity scale */	int	*h;	/* filter coefficients */	int	*hΔ;	/* coefficient deltas for interpolation */ 	int	wx;	/* extra samples */	int	ix;	/* buffer index */	int	nx;	/* buffer size */	int	*x;	/* the buffer */}; struct Pcmconv{	Pcmdesc	idesc;	Pcmdesc	odesc;	void	(*iconv)(int *, uchar *, int, int, int);	void	(*oconv)(int *, uchar *, int, int, int);	int	*in;	int	*out;	uchar	*buf;	int	nbuf;	ulong	prnd;	int	flags;	Chan	ch[];}; enum {	Nl	= 8,		/* 2^Nl samples per zero crossing in fir */	Nη	= 8,		/* phase bits for filter interpolation */	Np	= Nl+Nη,	/* phase bits (fract of fixed point) */	One	= 1<<Np,	Fcopy	= 1<<0,	Nin	= 2048,}; #define MAXINT	((int)(~0UL>>1))#define MININT	(MAXINT+1) static intclip(vlong v){	if(v > MAXINT)		return MAXINT;	if(v < MININT)		return MININT;	return v;} static intchaninit(Chan *c, int irate, int orate, int count, uintptr caller){	static int h[] = {#include "fir.h"	};	static int hΔ[nelem(h)], init = 0;	int n; 	c->ρ = ((uvlong)orate<<Np)/irate;	if(c->ρ == One)		goto Done; 	c->tΔ = ((uvlong)irate<<Np)/orate;	c->lΔ = 1<<(Nl+Nη);	c->le = nelem(h)<<Nη;	c->wx = 1 + (c->le / c->lΔ);	c->u = 13128;	/* unity scale factor for fir */	if(c->ρ < One){		c->u *= c->ρ;		c->u >>= Np;		c->lΔ *= c->ρ;		c->lΔ >>= Np;		c->wx *= c->tΔ;		c->wx >>= Np;	}	if(!init){		for(n=0; n<nelem(hΔ)-1; n++)			hΔ[n] = h[n+1] - h[n];		init = 1;	}	c->h = h;	c->hΔ = hΔ;	c->ix = c->wx;	c->t = c->ix<<Np;	c->nx = c->wx*2 + count;	c->x = mallocz(sizeof(c->x[0]) * c->nx, 1);	if(c->x == nil){		werrstr("memory");		return -1;	}	setmalloctag(c->x, caller);	count += c->nx; /* account for buffer accumulation */Done:	return ((uvlong)count * c->ρ) >> Np;} static intfilter(Chan *c){	ulong l, lΔ, le, p, i;	int *x, *h, *hΔ, a;	vlong v; 	v = 0; 	h = c->h;	hΔ = c->hΔ;	lΔ = c->lΔ;	le = c->le; 	/* left side */	x = &c->x[c->t>>Np];	p = c->t & ((1<<Np)-1);	l = c->ρ < One ? (c->ρ * p)>>Np : p;	while(l < le){		i = l >> Nη;		a = l & ((1<<Nη)-1);		l += lΔ;		a *= hΔ[i];		a >>= Nη;		a += h[i];		v += (vlong)*(--x) * a;	} 	/* right side */	x = &c->x[c->t>>Np];	p = (One - p) & ((1<<Np)-1);	l = c->ρ < One ? (c->ρ * p)>>Np : p;	if(p == 0) /* skip h[0] as it was already been summed above if p == 0 */		l += c->lΔ;	while(l < le){		i = l >> Nη;		a = l & ((1<<Nη)-1);		l += lΔ;		a *= hΔ[i];		a >>= Nη;		a += h[i];		v += (vlong)*x++ * a;	} 	/* scale */	v >>= 2;	v *= c->u;	v >>= 27; 	return clip(v);} static int*resample(Chan *c, int *x, int *y, int count){	ulong e;	int i, n; 	if(c->ρ == One){		/* no rate conversion needed */		if(count > 0)			memmove(y, x, count*sizeof(int));		return y+count;	} 	if(count == 0){		/* stuff zeros to drain last samples out */		while(c->ix < 2*c->wx)			c->x[c->ix++] = 0;	} 	do {		/* fill buffer */		for(i = c->ix, n = c->nx; count > 0 && i < n; count--, i++)			c->x[i] = *x++;		c->ix = i; 		/* need at least 2*wx samples in buffer for filter */		if(i < 2*c->wx)			break; 		/* process buffer */		e = (i - c->wx)<<Np;		while(c->t < e){			*y++ = filter(c);			c->t += c->tΔ;		} 		/* check if we'r at the end of buffer and wrap it */		e = c->t >> Np;		if(e >= (c->nx - c->wx)){			c->t -= e << Np;			c->t += c->wx << Np;			n = c->t >> Np;			n -= c->wx;			e -= c->wx;			i -= e;			if(i > 0){				memmove(c->x + n, c->x + e, i*sizeof(int));				n += i;			}			c->ix = n;		}	} while(count > 0); 	return y;} static ulongdither(int *y, int ibits, int obits, int count, ulong prnd){	if(ibits >= 32 || obits >= ibits)		return prnd; 	while(count--){		prnd = (prnd*0x19660dL + 0x3c6ef35fL) & 0xffffffffL;		*y = clip((vlong)*y + ((int)prnd >> ibits));		y++;	}	return prnd;} static voidmixin(int *y, int *x, int count){	while(count--){		*y = clip((vlong)*y + *x++);		y++;	}} static voidsiconv(int *dst, uchar *src, int bits, int skip, int count){	int i, v, s, b; 	b = (bits+7)/8;	s = sizeof(int)*8-bits;	while(count--){		v = 0;		i = b;		switch(b){		case 4:			v = src[--i];		case 3:			v = (v<<8) | src[--i];		case 2:			v = (v<<8) | src[--i];		case 1:			v = (v<<8) | src[--i];		}		*dst++ = v << s;		src += skip;	}} static voidSiconv(int *dst, uchar *src, int bits, int skip, int count){	int i, v, s, b; 	b = (bits+7)/8;	s = sizeof(int)*8-bits;	while(count--){		v = 0;		i = 0;		switch(b){		case 4:			v = src[i++];		case 3:			v = (v<<8) | src[i++];		case 2:			v = (v<<8) | src[i++];		case 1:			v = (v<<8) | src[i];		}		*dst++ = v << s;		src += skip;	}} static voiduiconv(int *dst, uchar *src, int bits, int skip, int count){	int i, s, b;	uint v; 	b = (bits+7)/8;	s = sizeof(uint)*8-bits;	while(count--){		v = 0;		i = b;		switch(b){		case 4:			v = src[--i];		case 3:			v = (v<<8) | src[--i];		case 2:			v = (v<<8) | src[--i];		case 1:			v = (v<<8) | src[--i];		}		*dst++ = (v << s) - (~0UL>>1);		src += skip;	}} static voidUiconv(int *dst, uchar *src, int bits, int skip, int count){	int i, s, b;	uint v; 	b = (bits+7)/8;	s = sizeof(uint)*8-bits;	while(count--){		v = 0;		i = 0;		switch(b){		case 4:			v = src[i++];		case 3:			v = (v<<8) | src[i++];		case 2:			v = (v<<8) | src[i++];		case 1:			v = (v<<8) | src[i];		}		*dst++ = (v << s) - (~0UL>>1);		src += skip;	}} static voidficonv(int *dst, uchar *src, int bits, int skip, int count){	if(bits == 32){		while(count--){			float f; 			f = *((float*)src), src += skip;			if(f > 1.0)				*dst++ = MAXINT;			else if(f < -1.0)				*dst++ = MININT;			else				*dst++ = f*((float)MAXINT);		}	} else {		while(count--){			double d; 			d = *((double*)src), src += skip;			if(d > 1.0)				*dst++ = MAXINT;			else if(d < -1.0)				*dst++ = MININT;			else				*dst++ = d*((double)MAXINT);		}	}} static voidaiconv(int *dst, uchar *src, int, int skip, int count){	int t, seg;	uchar a; 	while(count--){		a = *src, src += skip;		a ^= 0x55;		t = (a & 0xf) << 4;		seg = (a & 0x70) >> 4;		switch(seg){		case 0:			t += 8;			break;		case 1:			t += 0x108;			break;		default:			t += 0x108;			t <<= seg - 1;		}		t = (a & 0x80) ? t : -t;		*dst++ = t << (sizeof(int)*8 - 16);	}} static voidµiconv(int *dst, uchar *src, int, int skip, int count){	int t;	uchar u; 	while(count--){		u = *src, src += skip;		u = ~u;		t = ((u & 0xf) << 3) + 0x84;		t <<= (u & 0x70) >> 4;		t = u & 0x80 ? 0x84 - t: t - 0x84;		*dst++ = t << (sizeof(int)*8 - 16);	}} static voidsoconv(int *src, uchar *dst, int bits, int skip, int count){	int i, v, s, b; 	b = (bits+7)/8;	s = sizeof(int)*8-bits;	while(count--){		v = *src++ >> s;		i = 0;		switch(b){		case 4:			dst[i++] = v, v >>= 8;		case 3:			dst[i++] = v, v >>= 8;		case 2:			dst[i++] = v, v >>= 8;		case 1:			dst[i] = v;		}		dst += skip;	}} static voidSoconv(int *src, uchar *dst, int bits, int skip, int count){	int i, v, s, b; 	b = (bits+7)/8;	s = sizeof(int)*8-bits;	while(count--){		v = *src++ >> s;		i = b;		switch(b){		case 4:			dst[--i] = v, v >>= 8;		case 3:			dst[--i] = v, v >>= 8;		case 2:			dst[--i] = v, v >>= 8;		case 1:			dst[--i] = v;		}		dst += skip;	}} static voiduoconv(int *src, uchar *dst, int bits, int skip, int count){	int i, s, b;	uint v; 	b = (bits+7)/8;	s = sizeof(uint)*8-bits;	while(count--){		v = ((~0UL>>1) + *src++) >> s;		i = 0;		switch(b){		case 4:			dst[i++] = v, v >>= 8;		case 3:			dst[i++] = v, v >>= 8;		case 2:			dst[i++] = v, v >>= 8;		case 1:			dst[i] = v;		}		dst += skip;	}} static voidUoconv(int *src, uchar *dst, int bits, int skip, int count){	int i, s, b;	uint v; 	b = (bits+7)/8;	s = sizeof(uint)*8-bits;	while(count--){		v = ((~0UL>>1) + *src++) >> s;

Lines 1–500 of 738.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t