mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
fix unstable playback in browser runtime
This commit is contained in:
@@ -3,13 +3,17 @@ class APU extends AudioWorkletProcessor {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.sampleIndex = 0;
|
this.sampleIndex = 0;
|
||||||
|
this.currentTime = 0;
|
||||||
|
this.isFirstMessage = true;
|
||||||
|
this.pendingUpdates = [];
|
||||||
this.port.onmessage = (ev) => {
|
this.port.onmessage = (ev) => {
|
||||||
if(this.memory) {
|
if(this.memory) {
|
||||||
if(isNaN(ev.data)) {
|
if(this.isFirstMessage)
|
||||||
U8(this.memory.buffer, 80, 32).set(U8(ev.data));
|
{
|
||||||
} else {
|
this.currentTime += (ev.data.t - this.currentTime) / 8;
|
||||||
this.startTime = ev.data;
|
this.isFirstMessage = false;
|
||||||
}
|
}
|
||||||
|
this.pendingUpdates.push(ev.data);
|
||||||
} else {
|
} else {
|
||||||
this.load(ev.data[0], ev.data[1]);
|
this.load(ev.data[0], ev.data[1]);
|
||||||
}
|
}
|
||||||
@@ -55,9 +59,13 @@ class APU extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process(inputs, outputs, parameters) {
|
process(inputs, outputs, parameters) {
|
||||||
if(this.snd && this.startTime) {
|
this.isFirstMessage = true;
|
||||||
|
if(this.snd) {
|
||||||
|
while(this.pendingUpdates.length > 0 && this.pendingUpdates[0].t <= this.currentTime) {
|
||||||
|
U8(this.memory.buffer, 80, 32).set(U8(this.pendingUpdates.shift().r));
|
||||||
|
}
|
||||||
let u32Mem = new Uint32Array(this.memory.buffer);
|
let u32Mem = new Uint32Array(this.memory.buffer);
|
||||||
u32Mem[16] = Date.now() - this.startTime;
|
u32Mem[16] = this.currentTime;
|
||||||
let channels = outputs[0];
|
let channels = outputs[0];
|
||||||
let index = this.sampleIndex;
|
let index = this.sampleIndex;
|
||||||
let numSamples = channels[0].length;
|
let numSamples = channels[0].length;
|
||||||
@@ -66,6 +74,7 @@ class APU extends AudioWorkletProcessor {
|
|||||||
channels[1][i] = this.snd(index++);
|
channels[1][i] = this.snd(index++);
|
||||||
}
|
}
|
||||||
this.sampleIndex = index & 0xffffffff;
|
this.sampleIndex = index & 0xffffffff;
|
||||||
|
this.currentTime += numSamples / 44.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
audioContext.close();
|
audioContext.close();
|
||||||
keepRunning = false;
|
keepRunning = false;
|
||||||
abortController.abort();
|
abortController.abort();
|
||||||
}
|
};
|
||||||
|
|
||||||
let cartridgeSize = data.byteLength;
|
let cartridgeSize = data.byteLength;
|
||||||
|
|
||||||
@@ -232,7 +232,6 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
let startTime = Date.now();
|
let startTime = Date.now();
|
||||||
|
|
||||||
const timePerFrame = 1000 / 60;
|
const timePerFrame = 1000 / 60;
|
||||||
let nextFrame = startTime;
|
|
||||||
|
|
||||||
audioNode.connect(audioContext.destination);
|
audioNode.connect(audioContext.destination);
|
||||||
|
|
||||||
@@ -244,12 +243,10 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
isPaused = false;
|
isPaused = false;
|
||||||
audioContext.resume();
|
audioContext.resume();
|
||||||
startTime += now - pauseTime;
|
startTime += now - pauseTime;
|
||||||
audioNode.port.postMessage(startTime);
|
|
||||||
} else {
|
} else {
|
||||||
isPaused = true;
|
isPaused = true;
|
||||||
audioContext.suspend();
|
audioContext.suspend();
|
||||||
pauseTime = now;
|
pauseTime = now;
|
||||||
audioNode.port.postMessage(0);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('focus', () => updateVisibility(true), { signal: abortController.signal });
|
window.addEventListener('focus', () => updateVisibility(true), { signal: abortController.signal });
|
||||||
@@ -263,6 +260,7 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
let restart = false;
|
let restart = false;
|
||||||
|
let thisFrame;
|
||||||
if (!isPaused) {
|
if (!isPaused) {
|
||||||
let gamepads = navigator.getGamepads();
|
let gamepads = navigator.getGamepads();
|
||||||
let gamepad = 0;
|
let gamepad = 0;
|
||||||
@@ -291,7 +289,8 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let u32Mem = U32(memory.buffer);
|
let u32Mem = U32(memory.buffer);
|
||||||
u32Mem[16] = Date.now() - startTime;
|
let time = Date.now() - startTime;
|
||||||
|
u32Mem[16] = time;
|
||||||
u32Mem[17] = pad | gamepad;
|
u32Mem[17] = pad | gamepad;
|
||||||
if(instance.exports.upd) {
|
if(instance.exports.upd) {
|
||||||
instance.exports.upd();
|
instance.exports.upd();
|
||||||
@@ -300,16 +299,21 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
|
|
||||||
let soundRegisters = new ArrayBuffer(32);
|
let soundRegisters = new ArrayBuffer(32);
|
||||||
U8(soundRegisters).set(U8(memory.buffer, 80, 32));
|
U8(soundRegisters).set(U8(memory.buffer, 80, 32));
|
||||||
audioNode.port.postMessage(soundRegisters, [soundRegisters]);
|
audioNode.port.postMessage({t: time, r: soundRegisters}, [soundRegisters]);
|
||||||
|
|
||||||
let palette = U32(memory.buffer, 0x13000, 1024);
|
let palette = U32(memory.buffer, 0x13000, 1024);
|
||||||
for (let i = 0; i < 320 * 240; ++i) {
|
for (let i = 0; i < 320 * 240; ++i) {
|
||||||
buffer[i] = palette[memU8[i + 120]] | 0xff000000;
|
buffer[i] = palette[memU8[i + 120]] | 0xff000000;
|
||||||
}
|
}
|
||||||
canvasCtx.putImageData(imageData, 0, 0);
|
canvasCtx.putImageData(imageData, 0, 0);
|
||||||
|
|
||||||
|
let timeOffset = ((time * 6) % 100 - 50) / 6;
|
||||||
|
thisFrame = startTime + time - timeOffset / 2;
|
||||||
|
} else {
|
||||||
|
thisFrame = Date.now();
|
||||||
}
|
}
|
||||||
let now = Date.now();
|
let now = Date.now();
|
||||||
nextFrame = Math.max(nextFrame + timePerFrame, now);
|
let nextFrame = Math.max(thisFrame + timePerFrame, now);
|
||||||
|
|
||||||
if (restart) {
|
if (restart) {
|
||||||
runModule(currentData);
|
runModule(currentData);
|
||||||
|
|||||||
Reference in New Issue
Block a user