ref: 985df234d6be7a128dc60c827685eddba4112ff0
parent: 2823498ac38c9c57e9a6a4ffe4c19d108cf1806a
author: cinap_lenrek <[email protected]>
date: Wed Dec 12 10:46:12 EST 2012
audio/pcmconv: implement filter coefficient interpolation, cleanup
--- a/sys/src/cmd/audio/pcmconv/pcmconv.c
+++ b/sys/src/cmd/audio/pcmconv/pcmconv.c
@@ -21,8 +21,11 @@
ulong tΔ; /* output step */
ulong lΔ; /* filter step */
+ ulong le; /* filter end */
- ulong u; /* unity scale */
+ int *h; /* filter coefficients */
+ int *hΔ; /* coefficient deltas for interpolation */
+ int u; /* unity scale */
int wx; /* extra samples */
int ix; /* buffer index */
@@ -32,7 +35,7 @@
enum {
Nl = 8,
- Nη = 8, /* for coefficient interpolation, not implenented */
+ Nη = 8,
Np = Nl+Nη,
L = 1<<Np,
@@ -44,10 +47,15 @@
void
chaninit(Chan *c, int irate, int orate, int count)
{
+ static int h[] = {
+#include "fir.h"
+ };
+ static int hΔ[nelem(h)], init = 0;
+ int n;
+
c->ρ = ((uvlong)orate<<Np)/irate;
- if(0 && c->ρ == One)
+ if(c->ρ == One)
return;
- c->u = 13128; /* unity scale factor for fir */
c->tΔ = ((uvlong)irate<<Np)/orate;
c->lΔ = L;
if(c->ρ < One){
@@ -56,6 +64,15 @@
c->lΔ *= c->ρ;
c->lΔ >>= Np;
}
+ c->le = nelem(h)<<Nη;
+ c->h = h;
+ if(!init){
+ init = 1;
+ for(n=0; n<nelem(hΔ)-1; n++)
+ hΔ[n] = h[n+1] - h[n];
+ }
+ c->hΔ = hΔ;
+ c->u = 13128; /* unity scale factor for fir */
c->wx = 2*Nz*irate / orate;
c->ix = c->wx;
c->t = c->ix<<Np;
@@ -66,32 +83,46 @@
int
filter(Chan *c)
{
- ulong l, n, p;
+ ulong l, lΔ, le, p, i;
+ int *x, *h, *hΔ, a;
vlong v;
- static int h[] = {
-#include "fir.h"
- };
-
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;
- for(n = c->t>>Np; l < nelem(h)<<Nη; l += c->lΔ)
- v += (vlong)c->x[--n] * h[l>>Nη];
+ 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;
- n = c->t>>Np;
- if(p == 0){
- /* skip h[0] as it was already been summed above if p == 0 */
+ if(p == 0) /* skip h[0] as it was already been summed above if p == 0 */
l += c->lΔ;
- n++;
+ 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;
}
- for(; l < nelem(h)<<Nη; l += c->lΔ)
- v += (vlong)c->x[n++] * h[l>>Nη];
/* scale */
v >>= 2;
@@ -151,8 +182,11 @@
n = c->t >> Np;
n -= c->wx;
e -= c->wx;
- while(e < i)
- c->x[n++] = c->x[e++];
+ i -= e;
+ if(i > 0){
+ memmove(c->x + n, c->x + e, i*sizeof(int));
+ n += i;
+ }
c->ix = n;
}
} while(count > 0);