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
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 |