makepad/libs/score_player/shaders/epiano.splash

40 lines
1.3 KiB
Text

// Electric piano from two phase-modulation pairs: a 1:1 body whose index
// follows velocity (louder is brighter) and a ratio-14 tine ping that dies
// in ~100 ms; a gentle tremolo and a keyboard-scaled decay.
let bright = param(1.0, 0, 3)
let tine = param(0.7, 0, 2)
let decay = param(2.5, 0.2, 10)
let release = param(0.3, 0.02, 3)
let tremolo = param(0.15, 0, 1)
let gain = param(0.45, 0, 1)
var pb = 0.0
var pm = 0.0
var pt = 0.0
var trem = 0.0
var t = 0.0
var amp = Adsr{}
fn voice() {
if trigger {
t = 0.0
}
t = t + 1.0 / sample_rate
let dt = freq / sample_rate
pb = advance(pb, dt)
pm = advance(pm, dt)
pt = advance(pt, dt * 14.0)
trem = advance(trem, 5.5 / sample_rate)
// Higher notes decay faster.
let d = decay * exp2((60.0 - note) / 24.0)
let body_index = bright * velocity * (0.3 + 1.7 * exp(-t * 3.0))
let body = sin(TAU * pb + body_index * sin(TAU * pm))
let ping = sin(TAU * pb + tine * velocity * sin(TAU * pt) * exp(-t * 30.0))
let e = adsr(amp, 0.001, d, 0.0, release)
if gate == 0.0 && e == 0.0 {
stop()
}
let x = (body * 0.8 + (ping - body) * 0.35) * e * gain * (0.4 + 0.6 * velocity)
let tr = 1.0 - tremolo * 0.5 * (1.0 + sin(TAU * trem))
pan(x * tr, 0.3 * sin(TAU * trem))
}