Skip to content

Instantly share code, notes, and snippets.

@mharju
Last active December 14, 2015 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mharju/5159260 to your computer and use it in GitHub Desktop.
Save mharju/5159260 to your computer and use it in GitHub Desktop.
Not so buggy filter code
// Ah. Better.
typedef struct {
float x1, x2, y1, y2;
float c0, c1, c2, c3, c4;
} biquad_t;
typedef enum {
HIGH_SHELF,
LOW_SHELF,
PEAK_EQ
} biquad_filter_type_t;
//
#include <math.h>
#include <stdlib.h>
#include "biquad.h"
biquad_t* biquad_new(biquad_filter_type_t type, float f0, float dbGain, float Q) {
biquad_t *filter = (biquad_t*)malloc(sizeof(biquad_t));
filter->type = type;
biquad_update_params(filter, f0, dbGain, Q);
return filter;
}
void biquad_update_params(biquad_t* filter, float f0, float dbGain, float Q) {
float A = pow(10, (dbGain/40));
float w0 = 2 * M_PI * f0 / 48000;
float alpha = sin(w0)/(2*Q);
float a0, a1, a2, b0, b1, b2;
float A_alpha = 2*sqrt(A)*alpha;
float cos_w0 = cos(w0);
switch(filter->type) {
case HIGH_SHELF:
a0 = (A+1) - (A-1)*cos_w0 + A_alpha,
a1 = 2*( (A-1) - (A+1)*cos_w0);
a2 = (A+1) - (A-1)*cos_w0 - A_alpha;
b0 = A*( (A+1) + (A-1)*cos_w0 + A_alpha);
b1 = -2*A*( (A-1) + (A+1)*cos_w0);
b2 = A*((A+1) + (A-1)*cos_w0 - A_alpha);
break;
case LOW_SHELF:
a0 = (A+1) + (A-1)*cos_w0 + A_alpha;
a1 = -2*((A-1) + (A+1)*cos_w0);
a2 = (A+1) + (A-1)*cos_w0 - A_alpha;
b0 = A*( (A+1) - (A-1)*cos_w0 + A_alpha);
b1 = 2*A*( (A-1) - (A+1)*cos_w0);
b2 = A*( (A+1) - (A-1)*cos_w0 - A_alpha);
break;
case PEAK_EQ:
a0 = 1 + alpha/A;
a1 = -2*cos_w0;
a2 = 1 - alpha/A;
b0 = 1 + alpha*A;
b1 = -2*cos_w0;
b2 = 1 - alpha*A;
break;
}
filter->c0 = b0/a0;
filter->c1 = b1/a0;
filter->c2 = b2/a0;
filter->c3 = a1/a0;
filter->c4 = a2/a0;
filter->x1 = filter->x2 = filter->y2 = filter->y1 = 0;
}
float biquad_process_sample(float input, biquad_t *filter) {
float result =
filter->c0 * input +
filter->c1 * filter->x1 +
filter->c2 * filter->x2 -
filter->c3 * filter->y1 -
filter->c4 * filter->y2;
filter->x2 = filter->x1;
filter->x1 = input;
filter->y2 = filter->y1;
filter->y1 = result;
return result;
}
//
static biquad_t *high_shelf[2] = {NULL, NULL};
static biquad_t *low_shelf[2] = {NULL, NULL};
float cascade(float in)
{
biquad_t* hs = high_shelf[channel];
biquad_t* ls = low_shelf[channel];
if(hs == NULL || ls == NULL) {
hs = high_shelf[channel] = biquad_new(HIGH_SHELF, 1479, 9.0, 4.0);
ls = low_shelf[channel] = biquad_new(LOW_SHELF, 22.0, 9.0, 3.9);
}
return biquad_process_sample(biquad_process_sample(in, hs), ls);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment