wait for audio ready before starting cart, add button to unsuspend audio

fixes missing sound when auto-starting cart in chrome
This commit is contained in:
2022-03-06 14:08:44 +01:00
parent 0d514c7dd3
commit 2033f9a172
5 changed files with 52 additions and 8 deletions

View File

@@ -39,6 +39,8 @@ class APU extends AudioWorkletProcessor {
let instance = await instantiate(data); let instance = await instantiate(data);
this.snd = instance.exports.snd; this.snd = instance.exports.snd;
this.port.postMessage(2);
} }
process(inputs, outputs, parameters) { process(inputs, outputs, parameters) {

View File

@@ -13,8 +13,9 @@
<a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.1.2 <a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.1.2
</div> </div>
<div id="centered"> <div id="centered">
<canvas id="screen" width="320" height="240"> <canvas class="screen" id="screen" width="320" height="240">
</canvas> </canvas>
<button class="screen" id="start" style="display:none">Click to start</button>
<div id="timer" hidden="true"></div> <div id="timer" hidden="true"></div>
<div id="message"></div> <div id="message"></div>
<button id="cartButton" style="visibility:hidden">Load cart...</button> <button id="cartButton" style="visibility:hidden">Load cart...</button>

View File

@@ -12,6 +12,7 @@ let uw8 = MicroW8(document.getElementById('screen'), {
setMessage, setMessage,
keyboardElement: window, keyboardElement: window,
timerElement: document.getElementById("timer"), timerElement: document.getElementById("timer"),
startButton: document.getElementById("start")
}); });
function runModuleFromHash() { function runModuleFromHash() {

View File

@@ -104,9 +104,6 @@ export default function MicroW8(screen, config = {}) {
keepRunning = false; keepRunning = false;
} }
await audioContext.audioWorklet.addModule(audioWorkletUrl);
let audioNode = new AudioNode(audioContext);
let cartridgeSize = data.byteLength; let cartridgeSize = data.byteLength;
config.setMessage(cartridgeSize); config.setMessage(cartridgeSize);
@@ -114,6 +111,40 @@ export default function MicroW8(screen, config = {}) {
return; return;
} }
await audioContext.audioWorklet.addModule(audioWorkletUrl);
let audioNode = new AudioNode(audioContext);
let audioReadyFlags = 0;
let audioReadyResolve;
let audioReadyPromise = new Promise(resolve => audioReadyResolve = resolve);
let updateAudioReady = (f) => {
audioReadyFlags |= f;
if(audioReadyFlags == 3 && audioReadyResolve) {
audioReadyResolve(true);
audioReadyResolve = null;
}
};
audioNode.port.onmessage = (e) => updateAudioReady(e.data);
let audioStateChange = () => {
if(audioContext.state == 'suspended') {
if(config.startButton) {
config.startButton.style = '';
screen.style = 'display:none';
}
(config.startButton || screen).onclick = () => {
audioContext.resume();
};
} else {
if(config.startButton) {
config.startButton.style = 'display:none';
screen.style = '';
}
updateAudioReady(1);
}
};
audioContext.onstatechange = audioStateChange;
audioStateChange();
currentData = data; currentData = data;
let newURL = window.location.pathname; let newURL = window.location.pathname;
@@ -190,6 +221,8 @@ export default function MicroW8(screen, config = {}) {
let buffer = U32(imageData.data.buffer); let buffer = U32(imageData.data.buffer);
await audioReadyPromise;
let startTime = Date.now(); let startTime = Date.now();
const timePerFrame = 1000 / 60; const timePerFrame = 1000 / 60;

View File

@@ -37,7 +37,7 @@ a:hover {
color: #405040; color: #405040;
} }
#screen { .screen {
width: 320px; width: 320px;
height: 240px; height: 240px;
image-rendering: pixelated; image-rendering: pixelated;
@@ -45,9 +45,16 @@ a:hover {
margin-bottom: 8px; margin-bottom: 8px;
border: 4px solid #303040; border: 4px solid #303040;
box-shadow: 5px 5px 20px black; box-shadow: 5px 5px 20px black;
}
#screen {
cursor: none; cursor: none;
} }
#start {
font-size: 150%;
}
#timer::before { #timer::before {
content: ''; content: '';
display: inline-block; display: inline-block;
@@ -84,21 +91,21 @@ button:active {
} }
@media (min-width: 680px) and (min-height: 620px) { @media (min-width: 680px) and (min-height: 620px) {
#screen { .screen {
width: 640px; width: 640px;
height: 480px; height: 480px;
} }
} }
@media (min-width: 1000px) and (min-height: 800px) { @media (min-width: 1000px) and (min-height: 800px) {
#screen { .screen {
width: 960px; width: 960px;
height: 720px; height: 720px;
} }
} }
@media (width:640px) and (height:480px) { @media (width:640px) and (height:480px) {
#screen { .screen {
width: 640px; width: 640px;
height: 480px; height: 480px;
border: 0; border: 0;