mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
implement backchannel from audio thread
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -91,6 +91,7 @@ impl MicroW8 {
|
|||||||
struct Uw8Sound {
|
struct Uw8Sound {
|
||||||
stream: cpal::Stream,
|
stream: cpal::Stream,
|
||||||
tx: mpsc::SyncSender<[u8; 32]>,
|
tx: mpsc::SyncSender<[u8; 32]>,
|
||||||
|
rx: mpsc::Receiver<[u8; 32]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Runtime for MicroW8 {
|
impl super::Runtime for MicroW8 {
|
||||||
@@ -260,15 +261,27 @@ impl super::Runtime for MicroW8 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (tx, rx) = mpsc::sync_channel::<[u8; 32]>(1);
|
let (tx, rx) = mpsc::sync_channel::<[u8; 32]>(1);
|
||||||
|
let (back_tx, back_rx) = mpsc::sync_channel::<[u8; 32]>(2);
|
||||||
|
|
||||||
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let mut sample_index = 0;
|
let mut sample_index = 0;
|
||||||
let stream = {
|
let stream = {
|
||||||
device.build_output_stream(
|
device.build_output_stream(
|
||||||
&config,
|
&config,
|
||||||
move |buffer: &mut [f32], _| {
|
move |buffer: &mut [f32], _| {
|
||||||
if let Ok(regs) = rx.try_recv() {
|
if let Ok(mut regs) = rx.try_recv() {
|
||||||
memory.write(&mut store, 80, ®s).unwrap();
|
memory.write(&mut store, 80, ®s).unwrap();
|
||||||
|
memory.read(&mut store, 0x12c80, &mut regs).unwrap();
|
||||||
|
back_tx.send(regs).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let time = start_time.elapsed().as_millis() as i32;
|
||||||
|
let mem = memory.data_mut(&mut store);
|
||||||
|
mem[64..68].copy_from_slice(&time.to_le_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
for v in buffer {
|
for v in buffer {
|
||||||
*v = snd.call(&mut store, (sample_index,)).unwrap_or(0.0);
|
*v = snd.call(&mut store, (sample_index,)).unwrap_or(0.0);
|
||||||
sample_index = sample_index.wrapping_add(1);
|
sample_index = sample_index.wrapping_add(1);
|
||||||
@@ -280,7 +293,11 @@ impl super::Runtime for MicroW8 {
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Uw8Sound { stream, tx }
|
Uw8Sound {
|
||||||
|
stream,
|
||||||
|
tx,
|
||||||
|
rx: back_rx,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sound.stream.play()?;
|
sound.stream.play()?;
|
||||||
@@ -302,6 +319,13 @@ impl super::Runtime for MicroW8 {
|
|||||||
fn run_frame(&mut self) -> Result<()> {
|
fn run_frame(&mut self) -> Result<()> {
|
||||||
let mut result = Ok(());
|
let mut result = Ok(());
|
||||||
if let Some(mut instance) = self.instance.take() {
|
if let Some(mut instance) = self.instance.take() {
|
||||||
|
while let Ok(regs) = instance.sound.rx.try_recv() {
|
||||||
|
instance
|
||||||
|
.memory
|
||||||
|
.write(&mut instance.store, 0x12c80, ®s)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let time = instance.start_time.elapsed().as_millis() as i32;
|
let time = instance.start_time.elapsed().as_millis() as i32;
|
||||||
let mut gamepad: u32 = 0;
|
let mut gamepad: u32 = 0;
|
||||||
|
|||||||
@@ -5,7 +5,14 @@ class APU extends AudioWorkletProcessor {
|
|||||||
this.sampleIndex = 0;
|
this.sampleIndex = 0;
|
||||||
this.port.onmessage = (ev) => {
|
this.port.onmessage = (ev) => {
|
||||||
if(this.memory) {
|
if(this.memory) {
|
||||||
U8(this.memory.buffer, 80, 32).set(U8(ev.data));
|
if(isNaN(ev.data)) {
|
||||||
|
let data = U8(ev.data);
|
||||||
|
U8(this.memory.buffer, 80, 32).set(data);
|
||||||
|
data.set(U8(this.memory.buffer, 0x12c80, 32));
|
||||||
|
this.port.postMessage(ev.data);
|
||||||
|
} else {
|
||||||
|
this.startTime = ev.data;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.load(ev.data[0], ev.data[1]);
|
this.load(ev.data[0], ev.data[1]);
|
||||||
}
|
}
|
||||||
@@ -51,7 +58,9 @@ class APU extends AudioWorkletProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
process(inputs, outputs, parameters) {
|
process(inputs, outputs, parameters) {
|
||||||
if(this.snd) {
|
if(this.snd && this.startTime) {
|
||||||
|
let u32Mem = new Uint32Array(this.memory.buffer);
|
||||||
|
u32Mem[16] = Date.now() - this.startTime;
|
||||||
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;
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
audioReadyResolve = null;
|
audioReadyResolve = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
audioNode.port.onmessage = (e) => updateAudioReady(e.data);
|
|
||||||
let audioStateChange = () => {
|
let audioStateChange = () => {
|
||||||
if(audioContext.state == 'suspended') {
|
if(audioContext.state == 'suspended') {
|
||||||
if(config.startButton) {
|
if(config.startButton) {
|
||||||
@@ -211,6 +210,14 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
data = loadModuleData(data);
|
data = loadModuleData(data);
|
||||||
|
|
||||||
let platform_data = await loadModuleURL(platformUrl);
|
let platform_data = await loadModuleURL(platformUrl);
|
||||||
|
|
||||||
|
audioNode.port.onmessage = (e) => {
|
||||||
|
if(isNaN(e.data)) {
|
||||||
|
U8(memory.buffer, 0x12c80, 32).set(U8(e.data));
|
||||||
|
} else {
|
||||||
|
updateAudioReady(e.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
audioNode.port.postMessage([platform_data, data]);
|
audioNode.port.postMessage([platform_data, data]);
|
||||||
|
|
||||||
let platform_instance = await instantiate(platform_data);
|
let platform_instance = await instantiate(platform_data);
|
||||||
@@ -240,10 +247,12 @@ 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 });
|
||||||
|
|||||||
Reference in New Issue
Block a user