makepad/platform/script/audio_aot/shaders/waveshaper4x.splash

43 lines
1.1 KiB
Text

// Drive with 4x oversampling: zero-stuff to 4x, a 7-tap low-pass, the
// shaper (tanh with a bias for even harmonics), the same low-pass, keep
// every 4th sample. Clipping at 1x folds harmonics back as fizz; at 4x
// most of them stay above the audio band and get filtered.
let TAPS = [0.0135, 0.0976, 0.2356, 0.3066, 0.2356, 0.0976, 0.0135]
let drive = param(4.0, 1, 40)
let bias = param(0.1, -0.5, 0.5)
let mix = param(1.0, 0, 1)
struct Chan {
up: [0.0; 8]
dn: [0.0; 8]
w: int(0)
}
var ch = [Chan{}; 2]
fn fir(buf, w) {
let s = 0.0
for t in 0..7 {
s = s + TAPS[t] * buf[w - t]
}
s
}
fn oversampled(c, x) {
let out = 0.0
let dc = tanh(bias * drive)
for k in 0..4 {
c.up[c.w] = if k == 0 { x * 4.0 } else { 0.0 }
let u = fir(c.up, c.w)
c.dn[c.w] = tanh((u + bias) * drive) - dc
out = fir(c.dn, c.w)
c.w = c.w + 1
}
out / tanh(drive)
}
fn effect(l, r) {
let yl = oversampled(ch[0], l)
let yr = oversampled(ch[1], r)
vec2(l + (yl - l) * mix, r + (yr - r) * mix)
}