fix(Play Audio): Resume the web AudioContext on the first user gesture

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 <moussa.ahmed95@gmail.com>
This commit is contained in:
Ahmed Moussa committed 2026-10-09 13:07:37 +03:00
1 parent c51e5d5ec5
commit b63a13925b
3 files changed
+27

No files matched your search

+1
View File
@@ -9,3 +9,4 @@ plan/
/target-*/
/craft-fonts/
plans/
.DS_Store
+21
View File
@@ -15,6 +15,27 @@
</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&hellip;</div>
</body>
</html>
+5
View File
@@ -21,3 +21,8 @@
real_name = "Brandon Thomas"
display_name = "Brandon Thomas"
sync_github_name = false
[people.hamada147]
real_name = "Ahmed Moussa"
display_name = "Ahmed Moussa"
sync_github_name = true