diff options
Diffstat (limited to 'Alc/filters/filter.c')
-rw-r--r-- | Alc/filters/filter.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/Alc/filters/filter.c b/Alc/filters/filter.c index 4d757be7..fe59977b 100644 --- a/Alc/filters/filter.c +++ b/Alc/filters/filter.c @@ -9,7 +9,7 @@ extern inline void BiquadState_clear(BiquadState *filter); extern inline void BiquadState_copyParams(BiquadState *restrict dst, const BiquadState *restrict src); -extern inline void BiquadState_processPassthru(BiquadState *filter, const ALfloat *restrict src, ALsizei numsamples); +extern inline void BiquadState_processPassthru(BiquadState *filter, ALsizei numsamples); extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope); extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth); @@ -96,38 +96,43 @@ void BiquadState_setParams(BiquadState *filter, BiquadType type, ALfloat gain, A void BiquadState_processC(BiquadState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples) { - ALsizei i; if(LIKELY(numsamples > 1)) { - ALfloat x0 = filter->x[0]; - ALfloat x1 = filter->x[1]; - ALfloat y0 = filter->y[0]; - ALfloat y1 = filter->y[1]; + const ALfloat a1 = filter->a1; + const ALfloat a2 = filter->a2; + const ALfloat b0 = filter->b0; + const ALfloat b1 = filter->b1; + const ALfloat b2 = filter->b2; + ALfloat z1 = filter->z1; + ALfloat z2 = filter->z2; + ALsizei i; + /* Processing loop is transposed direct form II. This requires less + * storage versus direct form I (only two delay components, instead of + * a four-sample history; the last two inputs and outputs), and works + * better for floating-point which favors summing similarly-sized + * values while being less bothered by overflow. + * + * See: http://www.earlevel.com/main/2003/02/28/biquads/ + */ for(i = 0;i < numsamples;i++) { - dst[i] = filter->b0* src[i] + - filter->b1*x0 + filter->b2*x1 - - filter->a1*y0 - filter->a2*y1; - y1 = y0; y0 = dst[i]; - x1 = x0; x0 = src[i]; + ALfloat input = src[i]; + ALfloat output = input*b0 + z1; + z1 = input*b1 - output*a1 + z2; + z2 = input*b2 - output*a2; + dst[i] = output; } - filter->x[0] = x0; - filter->x[1] = x1; - filter->y[0] = y0; - filter->y[1] = y1; + filter->z1 = z1; + filter->z2 = z2; } else if(numsamples == 1) { - dst[0] = filter->b0 * src[0] + - filter->b1 * filter->x[0] + - filter->b2 * filter->x[1] - - filter->a1 * filter->y[0] - - filter->a2 * filter->y[1]; - filter->x[1] = filter->x[0]; - filter->x[0] = src[0]; - filter->y[1] = filter->y[0]; - filter->y[0] = dst[0]; + ALfloat input = *src; + ALfloat output = input*filter->b0 + filter->z1; + filter->z1 = input*filter->b1 - output*filter->a1 + filter->z2; + filter->z2 = input*filter->b2 - output*filter->a2; + *dst = output; } } |