You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

107 lines
2.1 KiB

/* CEM3320/Oberheim/Phrophet-style filter as described here: https://arxiv.org/pdf/2111.05592.pdf */
#include <math.h>
inline float clamp(float x, float a, float b) {
return fminf(b, fmaxf(a, x));
}
class SVF {
protected:
float as1, as2;
float kdiv;
float kK, kQ;
inline void updateCoeffs() {
kdiv = 1 + kK/kQ + kK*kK;
}
public:
typedef struct {
float hp;
float bp;
float lp;
float br;
float ap;
} Output;
SVF() {
as1 = 0;
as2 = 0;
kK = tan(M_PI_4);
kQ = M_SQRT1_2;
updateCoeffs();
}
void setFrequency(float f) {
kK = tan(M_PI_2 * clamp(f, 0, 1));
updateCoeffs();
}
void setQ(float q) {
kQ = q;
updateCoeffs();
}
Output tick(float as) {
Output out;
out.hp = (as - (1/kQ + kK) * as1 - as2) / kdiv;
float au = out.hp * kK;
out.bp = au + as1;
as1 = au + out.bp;
au = out.bp * kK;
out.lp = au + as2;
as2 = au + out.lp;
float abr = out.hp + out.lp;
float aap = out.hp+out.lp + (1/kQ) * out.bp;
return out;
}
};
class SVFx2 {
public:
enum Mode { MODE_HP, MODE_BP, MODE_LP, MODE_BR, MODE_AP };
private:
Mode mode;
SVF first, second;
public:
SVFx2() {
this->mode = MODE_LP;
}
void setMode(Mode mode) {
this->mode = mode;
}
void setFrequency(float f) {
first.setFrequency(f);
second.setFrequency(f);
}
void setQ(float q) {
first.setQ(q);
second.setQ(q);
}
float tick(float as) {
SVF::Output in = first.tick(as);
switch(mode) {
case MODE_HP:
return second.tick(in.hp).hp;
case MODE_BP:
return second.tick(in.bp).bp;
case MODE_LP:
return second.tick(in.lp).lp;
case MODE_BR:
return second.tick(in.br).br;
case MODE_AP:
return second.tick(in.ap).ap;
}
}
};