mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-14 14:26:46 -04:00
cpal (wasm) creates its output stream at startup, before any user gesture, so the browser leaves the WebAudio AudioContext 'suspended'. As a result no audio plays, and the transport clock never advances because the audio callback drives it. Wrap the AudioContext constructor before the wasm module loads so that every context cpal creates is captured. On the first pointer, mouse, touch or key event, resume any context that is still suspended. Signed-off-by: Ahmed Moussa <[email protected]>
42 lines
2.0 KiB
HTML
42 lines
2.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
<title>SoundCraft</title>
|
|
<link data-trunk rel="icon" type="image/png" href="../../assets/app-icon/hicolor/64x64/apps/ai.storyteller.soundcraft.png" />
|
|
<link data-trunk rel="rust" data-bin="soundcraft-web" data-wasm-opt="z" data-weak-refs />
|
|
<style>
|
|
html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #1e1f22; }
|
|
#soundcraft_canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
|
|
#soundcraft_loading { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
color: #b8b8b8; font: 14px system-ui, sans-serif; pointer-events: none; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<canvas id="soundcraft_canvas"></canvas>
|
|
<script>
|
|
// cpal (wasm) builds the output stream at startup, before any user gesture, so the
|
|
// WebAudio AudioContext stays 'suspended': no audio is heard and the transport clock
|
|
// (driven by the audio callback) never advances. Capture the AudioContext cpal creates
|
|
// and resume it on the first user gesture. Runs before the wasm module is instantiated.
|
|
(function () {
|
|
var Orig = window.AudioContext || window.webkitAudioContext;
|
|
if (!Orig) return;
|
|
var ctxs = [];
|
|
function Wrapped(opts) { var c = new Orig(opts); ctxs.push(c); return c; }
|
|
Wrapped.prototype = Orig.prototype;
|
|
window.AudioContext = Wrapped;
|
|
if (window.webkitAudioContext) window.webkitAudioContext = Wrapped;
|
|
function resumeAll() {
|
|
ctxs.forEach(function (c) { if (c.state === 'suspended') { c.resume().catch(function () {}); } });
|
|
}
|
|
['pointerdown', 'mousedown', 'touchstart', 'keydown'].forEach(function (ev) {
|
|
window.addEventListener(ev, resumeAll, { capture: true });
|
|
});
|
|
})();
|
|
</script>
|
|
<div id="soundcraft_loading">Loading SoundCraft…</div>
|
|
</body>
|
|
</html>
|