makepad/libs/score_player/shaders/echo.splash

50 lines
1.7 KiB
Text

// Stereo echo with cross-feedback: the left input first passes an ~11 ms
// side delay (Haas), each side's repeat feeds the other with its own
// feedback (asymmetric, so the repeats wander), the loop is band-limited
// (low-cut and high-cut, darker with every repeat), the returns get
// mid/side width. The time is `division` beats at `bpm` (the song tempo).
let bpm = param(120, 20, 300)
let division = param(0.75, 0.0625, 4)
let feedback_l = param(0.45, 0, 0.95)
let feedback_r = param(0.6, 0, 0.95)
let side_ms = param(11, 0, 40)
let low_cut = param(250, 20, 2000)
let high_cut = param(5000, 1000, 16000)
let spread = param(1.6, 0, 2)
let wet = param(0.3, 0, 1)
let MAX = 131072
var dl = [0.0; MAX]
var dr = [0.0; MAX]
var side = [0.0; 4096]
var w = int(0)
var hp_l = OnePole{}
var hp_r = OnePole{}
var lp_l = OnePole{}
var lp_r = OnePole{}
var d = 0.0
fn block() {
onepole_set(hp_l, low_cut)
onepole_set(hp_r, low_cut)
onepole_set(lp_l, high_cut)
onepole_set(lp_r, high_cut)
let target = min(60.0 / bpm * division * sample_rate, MAX - 4.0)
// Glide to a new time instead of jumping (no clicks on tempo changes).
d = if d == 0.0 { target } else { d + (target - d) * 0.2 }
}
fn effect(l, r) {
side[w] = l
let side_l = tap(side, w, max(side_ms * 0.001 * sample_rate, 0.0))
let el = tap(dl, w, d)
let er = tap(dr, w, d)
// Cross-feedback through the band-limited loop.
let fl = onepole_lp(lp_l, onepole_hp(hp_l, er)) * feedback_l
let fr = onepole_lp(lp_r, onepole_hp(hp_r, el)) * feedback_r
dl[w] = side_l + soft_clip(fl)
dr[w] = r + soft_clip(fr)
w = w + 1
let wide = width(vec2(el, er), spread)
vec2(l, r) + wide * wet
}