#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. Load more
#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 int clip(vlong v) { if(v > MAXINT) return MAXINT; if(v < MININT) return MININT; return v; } static int chaninit(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 int filter(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 ulong dither(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 void mixin(int *y, int *x, int count) { while(count--){ *y = clip((vlong)*y + *x++); y++; } } static void siconv(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 void Siconv(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 void uiconv(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 void Uiconv(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 void ficonv(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 void aiconv(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 void soconv(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 void Soconv(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 void uoconv(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 void Uoconv(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;