+struct dsp_biquad {
+ f32 a0, a1, a2, b1, b2, c0, d0,
+ xnz1, xnz2, ynz1, ynz2, offset;
+};
+
+static f32 dsp_biquad_process( struct dsp_biquad *bq, f32 xn ){
+ f32 yn = + bq->a0*xn + bq->a1*bq->xnz1 + bq->a2*bq->xnz2
+ - bq->b1*bq->ynz1 - bq->b2*bq->ynz2;
+ bq->xnz2 = bq->xnz1;
+ bq->xnz1 = xn;
+ bq->ynz2 = bq->ynz1;
+ bq->ynz1 = yn;
+ return yn + bq->offset;
+}
+
+static void dsp_init_biquad_butterworth_lpf( struct dsp_biquad *bq, f32 fc ){
+ f32 c = 1.0f/tanf(VG_PIf*fc / 44100.0f);
+ bq->a0 = 1.0f / (1.0f + sqrtf(2.0f)*c + powf(c, 2.0f) );
+ bq->a1 = 2.0f * bq->a0;
+ bq->a2 = bq->a0;
+ bq->b1 = 2.0f * bq->a0*(1.0f - powf(c, 2.0f));
+ bq->b2 = bq->a0 * (1.0f - sqrtf(2.0f)*c + powf(c, 2.0f) );
+}
+
+static inline void dsp_read_delay( struct dsp_delay *delay, float *s, u32 t ){
+ u32 index = delay->cur+t;