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.
bfde5e4High-frequency ringing: in-plane loss, band-limited listener sum, damping defaultsJeremy Magland 4// The ring buffer holds the transverse velocity at the sample instants; the
5// acceleration is the first difference of the delayed velocity, which is the
6// average acceleration over one sample interval (band-limited, and immune to
7// the per-step rounding noise of the force evaluation).
f8a8a6cNonlinear steel sheet gong simulator with WebGPUJeremy Magland 8
9@group(0) @binding(0) var<uniform> P: Params;
10@group(0) @binding(1) var<uniform> SP: StepParams;
11@group(0) @binding(2) var<storage, read> hist: array<f32>;
12@group(0) @binding(3) var<storage, read> lw: array<vec2f>;
13@group(0) @binding(4) var<storage, read_write> audioOut: array<f32>;
15var<workgroup> sh: array<f32, 256>;
17@compute @workgroup_size(256)
18fn main(@builtin(local_invocation_id) lid: vec3u) {
19 let t = lid.x;
20 let H = i32(P.histLen);
21 let slot = SP.audioSlot;
22 var acc = 0.0;
23 for (var k = t; k < P.n; k += 256u) {
24 let d = lw[k].y;
25 let k0 = i32(floor(d));
26 let f = d - f32(k0);
27 let s0 = ((slot - k0) % H + H) % H;
28 let s1 = ((slot - k0 - 1) % H + H) % H;
bfde5e4High-frequency ringing: in-plane loss, band-limited listener sum, damping defaultsJeremy Magland 29 let s2 = ((slot - k0 - 2) % H + H) % H;
30 let v0 = hist[u32(s0) * P.n + k];
31 let v1 = hist[u32(s1) * P.n + k];
32 let v2 = hist[u32(s2) * P.n + k];
33 let a = (mix(v0, v1, f) - mix(v1, v2, f)) * P.fs;
34 acc += lw[k].x * a;
36 sh[t] = acc;
37 workgroupBarrier();
38 for (var stride = 128u; stride > 0u; stride >>= 1u) {
39 if (t < stride) { sh[t] += sh[t + stride]; }
40 workgroupBarrier();
41 }
42 if (t == 0u) { audioOut[u32(SP.audioOut)] = sh[0]; }
43}