f8a8a6cNonlinear steel sheet gong simulator with WebGPUJeremy Magland 1// Retarded-time sum over the plate for one output sample (Rayleigh integral).
2// lw[k] = (weight, delay in samples) for node k; delay is relative to the
3// closest node so that the ring buffer only has to cover the spread.
5@group(0) @binding(0) var<uniform> P: Params;
6@group(0) @binding(1) var<uniform> SP: StepParams;
7@group(0) @binding(2) var<storage, read> hist: array<f32>;
8@group(0) @binding(3) var<storage, read> lw: array<vec2f>;
9@group(0) @binding(4) var<storage, read_write> audioOut: array<f32>;
11var<workgroup> sh: array<f32, 256>;
13@compute @workgroup_size(256)
14fn main(@builtin(local_invocation_id) lid: vec3u) {
15 let t = lid.x;
16 let H = i32(P.histLen);
17 let slot = SP.audioSlot;
18 var acc = 0.0;
19 for (var k = t; k < P.n; k += 256u) {
20 let d = lw[k].y;
21 let k0 = i32(floor(d));
22 let f = d - f32(k0);
23 let s0 = ((slot - k0) % H + H) % H;
24 let s1 = ((slot - k0 - 1) % H + H) % H;
25 let a0 = hist[u32(s0) * P.n + k];
26 let a1 = hist[u32(s1) * P.n + k];
27 acc += lw[k].x * mix(a0, a1, f);
28 }
29 sh[t] = acc;
30 workgroupBarrier();
31 for (var stride = 128u; stride > 0u; stride >>= 1u) {
32 if (t < stride) { sh[t] += sh[t + stride]; }
33 workgroupBarrier();
34 }
35 if (t == 0u) { audioOut[u32(SP.audioOut)] = sh[0]; }
36}