@thi.ng/dsp
Version:
Composable signal generators, oscillators, filters, FFT, spectrum, windowing & related DSP utils
80 lines (79 loc) • 1.83 kB
JavaScript
import { PI } from "@thi.ng/math/api";
import { clamp05 } from "@thi.ng/math/interval";
import { AProc } from "./aproc.js";
const svfLP = (fc, q) => new SVF("lp", fc, q);
const svfHP = (fc, q) => new SVF("hp", fc, q);
const svfBP = (fc, q) => new SVF("bp", fc, q);
const svfNotch = (fc, q) => new SVF("notch", fc, q);
const svfPeak = (fc, q) => new SVF("peak", fc, q);
const svfAllpass = (fc, q) => new SVF("all", fc, q);
class SVF extends AProc {
constructor(_type, _freq, _q = 0.5) {
super(0);
this._type = _type;
this._freq = _freq;
this._q = _q;
this.reset();
this.computeCoeffs();
}
_a1;
_a2;
_c1;
_c2;
_g;
_k;
reset() {
this._c1 = this._c2 = this._val = 0;
return this;
}
next(x) {
const { _c1, _c2 } = this;
const x1 = this._a1 * _c1 + this._a2 * (x - _c2);
const x2 = _c2 + this._g * x1;
this._c1 = 2 * x1 - _c1;
this._c2 = 2 * x2 - _c2;
switch (this._type) {
case "lp":
return this._val = x2;
case "hp":
return this._val = x - this._k * x1 - x2;
case "bp":
return this._val = x1;
case "notch":
return this._val = x - this._k * x1;
case "peak":
return this._val = 2 * x2 - x + this._k * x1;
case "all":
return this._val = x - 2 * this._k * x1;
}
}
set(fc, q) {
this._freq = fc;
this._q = q;
this.computeCoeffs();
}
setFreq(fc) {
this._freq = fc;
this.computeCoeffs();
}
setQ(q) {
this._q = q;
this.computeCoeffs();
}
computeCoeffs() {
this._freq = clamp05(this._freq);
const g = this._g = Math.tan(PI * this._freq);
this._k = 2 - 2 * this._q;
this._a1 = 1 / (1 + g * (g + this._k));
this._a2 = g * this._a1;
}
}
export {
SVF,
svfAllpass,
svfBP,
svfHP,
svfLP,
svfNotch,
svfPeak
};