diff --git a/static/ambient/index.html b/static/ambient/index.html index 32b33dc..a08a088 100644 --- a/static/ambient/index.html +++ b/static/ambient/index.html @@ -926,22 +926,26 @@ function buildWomb(K) { K.set = (a, b) => { sm(tl.frequency, 100 + 300 * b); sm(lp.frequency, 300 + 500 * b); }; } -// Zugfahrt: Rollgeräusch + Schienenstöße. Jeder Stoß wird von vier Achsen nacheinander angeschlagen -// (zwei pro Drehgestell, Abstand = halbe Schienenlänge) -> gleichmäßig "tschuck-tschuck ... tschuck-tschuck", Takt folgt der Geschwindigkeit. +// Zugfahrt: Rollgeräusch + Schienenstöße. Jeder Stoß wird von zwei Achsen kurz nacheinander angeschlagen +// (Achsabstand 3,1 m, Schienenlänge 33 m) -> "klack-klack ......... klack-klack", Pause ≈ 11× Paarabstand, Takt folgt der Geschwindigkeit. function railClack(K, t, amp) { const ctx = S.ctx, nb = noiseBuf("white"); - const s1 = ctx.createBufferSource(), bp = bq("bandpass", R(500, 1100) * (.7 + .8 * K.b), .9), g1 = ctx.createGain(); + const s1 = ctx.createBufferSource(), bp = bq("bandpass", R(300, 650) * (.7 + .8 * K.b), .8), g1 = ctx.createGain(); // dumpfer Anschlag s1.buffer = nb; s1.connect(bp).connect(g1).connect(K.out); - g1.gain.setValueAtTime(0, t); g1.gain.linearRampToValueAtTime(amp * .9, t + .003); g1.gain.exponentialRampToValueAtTime(.001, t + .07); + g1.gain.setValueAtTime(0, t); g1.gain.linearRampToValueAtTime(amp * .55, t + .004); g1.gain.exponentialRampToValueAtTime(.001, t + .08); s1.start(t, R(0, 8), .1); - const o = ctx.createOscillator(), og = ctx.createGain(); // dumpfer Schlag im Wagenboden - o.frequency.setValueAtTime(110, t); o.frequency.exponentialRampToValueAtTime(55, t + .1); - og.gain.setValueAtTime(0, t); og.gain.linearRampToValueAtTime(amp * .7, t + .004); og.gain.exponentialRampToValueAtTime(.001, t + .16); - o.connect(og).connect(K.out); o.start(t); o.stop(t + .2); - const s2 = ctx.createBufferSource(), rb = bq("bandpass", R(190, 260), 8), g2 = ctx.createGain(); // Nachklingen der Karosserie - s2.buffer = nb; s2.connect(rb).connect(g2).connect(K.out); - g2.gain.setValueAtTime(0, t); g2.gain.linearRampToValueAtTime(amp * .9, t + .004); g2.gain.exponentialRampToValueAtTime(.001, t + .35); - s2.start(t, R(0, 8), .4); + const o = ctx.createOscillator(), og = ctx.createGain(); // Schlag im Wagenboden + o.frequency.setValueAtTime(95, t); o.frequency.exponentialRampToValueAtTime(48, t + .12); + og.gain.setValueAtTime(0, t); og.gain.linearRampToValueAtTime(amp * .8, t + .005); og.gain.exponentialRampToValueAtTime(.001, t + .24); + o.connect(og).connect(K.out); o.start(t); o.stop(t + .3); + // Karosserie klingt nach: zwei Resonanzmoden, lang abklingend + const f1 = R(170, 220); + [[f1, 1.5, .65], [f1 * 1.9, .7, .45]].forEach(([f, a, dec]) => { + const s2 = ctx.createBufferSource(), rb = bq("bandpass", f, 10), g2 = ctx.createGain(); + s2.buffer = nb; s2.connect(rb).connect(g2).connect(K.out); + g2.gain.setValueAtTime(0, t); g2.gain.linearRampToValueAtTime(amp * a, t + .006); g2.gain.exponentialRampToValueAtTime(.001, t + dec); + s2.start(t, R(0, 8), dec + .1); + }); } function buildTrain(K) { const ctx = S.ctx, lp = bq("lowpass", 700, .6), g = ctx.createGain(), bp = bq("bandpass", 900, .5), bg = ctx.createGain(); @@ -960,8 +964,8 @@ function buildTrain(K) { const now = T(); while (K.nextJoint < now + 2.5) { // alle Achsen der Schienenstöße der nächsten Sekunden vorplanen (ein stockender Hauptthread reißt so keine Lücke) const v = K.v, t0 = K.nextJoint, amp = .8 * (.85 + Math.random() * .3); - [0, 2.5 / v, 12.5 / v, 15 / v].forEach((o, i) => railClack(K, t0 + o, amp * (i % 2 ? .8 : 1))); - K.nextJoint += 25 / v; + [0, 3.1 / v].forEach((o, i) => railClack(K, t0 + o, amp * (i ? .9 : 1))); // zwei Achsen des Drehgestells, dann Pause bis zum nächsten Stoß + K.nextJoint += 33 / v; } if (now > K.nextPoints) { // Weiche: kurzes schnelles Klapperbündel const n = 7 + Math.floor(Math.random() * 5); diff --git a/static/js/sw.js b/static/js/sw.js index 907ce35..45bdb3d 100644 --- a/static/js/sw.js +++ b/static/js/sw.js @@ -2,7 +2,7 @@ * diora service worker — caches the app shell for offline use. */ -const CACHE = 'diora-v80'; +const CACHE = 'diora-v81'; const SHELL = [ '/static/css/app.css', '/static/js/app.js',