Skip to content

Instantly share code, notes, and snippets.

@phkahler
Last active July 19, 2022 19:05
Show Gist options
  • Save phkahler/0d34bc446845a9d7fee7e1506d9b2b04 to your computer and use it in GitHub Desktop.
Save phkahler/0d34bc446845a9d7fee7e1506d9b2b04 to your computer and use it in GitHub Desktop.
Equalizer (8 band)
#include <math.h>
// A simple 8-band EQ. The filters are all first order so there is
// lot of overlap in adjacent bands. Never the less this should be
// a solid way to shape the tone of an audio signal.
// Aiming to eventually put this in OBS, which IMHO needs one.
// This is a Work In Progress.
//
// We will use a set of 7 filters to split a signal s into 8 bands
// |<----------------------------- s ----------------------------->|
// |<-------------s10------------->|<-------------s11------------->|
// |<-----s20----->|<-----s21----->|<-----s22----->|<-----s23----->|
// |<-s30->|<-s31->|<-s32->|<-s33->|<-s34->|<-s35->|<-s36->|<-s37->|
struct equalizer {
// sample frequency
float freq;
// user/slider gain settings
float g[8];
// internal gains for the 7 Low Pass Filters
float f1, f2, f3, f4, f5, f6, f7;
// odd numbered signals do not require storage across samples
float s10, s20, s22, s30, s32, s34, s36;
};
void equalizer_set_user_gains(struct equalizer *eq, float gain[8])
{
int i;
for (i=0; i<8; i++)
{
eq->g[i] = gain[i];
}
}
// we need the sample frequency and the 7 cutoff frequencies between bands
void equalizer_set_frequencies(struct equalizer *eq, float f,
float c1, float c2, float c3, float c4, float c5, float c6, float c7)
{
eq->freq = f;
// Calculate the filter gains (alpha) from cuttoff and sample frequencies
eq->f1 = 1.0 - exp(-2*3.14159265*c1/f);
eq->f2 = 1.0 - exp(-2*3.14159265*c2/f);
eq->f3 = 1.0 - exp(-2*3.14159265*c3/f);
eq->f4 = 1.0 - exp(-2*3.14159265*c4/f);
eq->f5 = 1.0 - exp(-2*3.14159265*c5/f);
eq->f6 = 1.0 - exp(-2*3.14159265*c6/f);
eq->f7 = 1.0 - exp(-2*3.14159265*c7/f);
}
// s is a sample of the input signal, out is the output sample
float equalizer_update(struct equalizer *eq, float s)
{
float s11, s21, s23, s31, s33, s35, s37;
// first LPF / HPF combination
eq->s10 += (s - eq->s10)*eq->f4;
s11 = s - eq->s10;
// second layer of filters
eq->s20 += (eq->s10 - eq->s20)*eq->f2;
eq->s22 += (s11 - eq->s22)*eq->f6;
s21 = eq->s10 - eq->s20;
s23 = s11 - eq->s22;
// third filter layer
eq->s30 += (eq->s20 - eq->s30)*eq->f1;
eq->s32 += (s21 - eq->s32)*eq->f3;
eq->s34 += (eq->s22 - eq->s34)*eq->f5;
eq->s36 += (s23 - eq->s36)*eq->f7;
s31 = eq->s20 - eq->s30;
s33 = s21 - eq->s32;
s35 = eq->s22 - eq->s34;
s37 = s23 - eq->s36;
// apply pass-band gains and sum
float out = eq->s30*eq->g[0] + s31*eq->g[1] + eq->s32*eq->g[2] + s33*eq->g[3];
out += eq->s34*eq->g[4] + s35*eq->g[5] + eq->s36*eq->g[6] + s37*eq->g[7];
return (out);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment