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.
 
 

117 lines
2.1 KiB

#ifndef __SVF_H__
#define __SVF_H__
/* CEM3320/Oberheim/Phrophet-style filter as described here: https://arxiv.org/pdf/2111.05592.pdf */
#include <math.h>
#include "util.h"
class SVF12 {
protected:
float as1, as2;
float kdiv;
float kK, kQ;
inline void updateCoeffs() {
kdiv = 1 + kK/kQ + kK*kK;
}
public:
typedef struct {
float hp; // high-pass
float bp; // band-pass
float lp; // low-pass
} Output;
SVF12() {
as1 = 0;
as2 = 0;
kK = tan(M_PI_4);
kQ = M_SQRT1_2;
updateCoeffs();
}
void setFrequency(float f) {
kK = tan(M_PI_4 * 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;
return out;
}
};
// 12 and 24 dB/oct
class SVF {
public:
enum Mode {
MODE_HP_12,
MODE_HP_24,
MODE_BP_12,
MODE_BP_24,
MODE_LP_12,
MODE_LP_24,
};
private:
Mode mode;
SVF12 first, second;
public:
SVF() {
this->mode = MODE_LP_24;
}
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) {
SVF12::Output in = first.tick(as);
switch(mode) {
case MODE_HP_12:
return in.hp;
case MODE_HP_24:
return second.tick(in.hp).hp;
case MODE_BP_12:
return in.bp;
case MODE_BP_24:
return second.tick(in.bp).bp;
case MODE_LP_12:
return in.lp;
case MODE_LP_24:
return second.tick(in.lp).lp;
}
}
};
#endif