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.
 
 

88 lines
2.0 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 {
public:
float frequency;
float resonance;
typedef struct {
float lp; // low-pass
float bp; // band-pass
float hp; // high-pass
} Output;
protected:
float as1, as2;
public:
SVF12() : as1(0), as2(0) {}
Output tick(float as, float freq, float Q) {
Output out;
float kK = tan(M_PI_4 * clamp(freq, 0, 1));
float kQ = fmaxf(0, Q);
float kdiv = 1 + kK/kQ + kK*kK;
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 Filter {
public:
enum Type {
TYPE_LP = 0,
TYPE_BP = 42,
TYPE_HP = 84
};
enum Slope {
SLOPE_24 = 0,
SLOPE_12 = 64,
};
typedef struct {
float freq;
float Q;
Type type;
Slope slope;
} Settings;
private:
const Settings* settings;
SVF12 first, second;
public:
Filter() = delete;
Filter(const Settings *settings): settings(settings) {}
inline float tick(float as, float freqMod) {
SVF12::Output in = first.tick(as, settings->freq + freqMod, settings->Q);
switch(settings->type) {
case TYPE_LP:
return settings->slope == SLOPE_24 ? second.tick(in.lp, settings->freq + freqMod, settings->Q).lp : in.lp;
case TYPE_BP:
return settings->slope == SLOPE_24 ? second.tick(in.bp, settings->freq + freqMod, settings->Q).bp : in.bp;
case TYPE_HP:
return settings->slope == SLOPE_24 ? second.tick(in.hp, settings->freq + freqMod, settings->Q).hp : in.hp;
}
}
};
#endif