remove back-channel from audio thread for now

It needs some more thought before committing to it.
This commit is contained in:
2022-04-24 15:52:19 +02:00
parent 491bf88ade
commit 2bf8938183
5 changed files with 9 additions and 35 deletions

View File

@@ -23,9 +23,7 @@ The memory has to be imported as `env` `memory` and has a maximum size of 256kb
00070-00078: reserved 00070-00078: reserved
00078-12c78: frame buffer 00078-12c78: frame buffer
12c78-12c7c: sound registers/work area base address (for sndGes function) 12c78-12c7c: sound registers/work area base address (for sndGes function)
12c7c-12c80: reserved 12c7c-13000: reserved
12c80-12ca0: sound data (synced from sound thread)
12ca0-13000: reserved
13000-13400: palette 13000-13400: palette
13400-13c00: font 13400-13c00: font
13c00-14000: reserved 13c00-14000: reserved
@@ -283,8 +281,7 @@ MicroW8 actually runs two instances of your module. On the first instance, it ca
second instance, it calls `snd` instead with an incrementing sample index and expects that function to return sound samples for the left and right second instance, it calls `snd` instead with an incrementing sample index and expects that function to return sound samples for the left and right
channel at 44100 Hz. If your module does not export a `snd` function, it calls the api function `sndGes` instead. channel at 44100 Hz. If your module does not export a `snd` function, it calls the api function `sndGes` instead.
As the only means of communication, 32 bytes starting at address 0x00050 are copied from main to sound memory after `upd` returns. At the same time, As the only means of communication, 32 bytes starting at address 0x00050 are copied from main to sound memory after `upd` returns.
32 bytes starting at 0x12c80 are copied from sound to main memory.
By default, the `sndGes` function generates sound based on the 32 bytes at 0x00050. This means that in the default configuration those 32 bytes act By default, the `sndGes` function generates sound based on the 32 bytes at 0x00050. This means that in the default configuration those 32 bytes act
as sound registers. See the `sndGes` function for the meaning of those registers. as sound registers. See the `sndGes` function for the meaning of those registers.
@@ -302,11 +299,12 @@ This implements a sound chip, generating sound based on 32 bytes of sound regist
The spec of this sound chip are: The spec of this sound chip are:
- 4 channels - 4 channels with individual volume control (0-15)
- rect, saw, tri, noise wave forms selectable per channel - rect, saw, tri, noise wave forms selectable per channel
- each wave form supports some kind of pulse width modulation - each wave form supports some kind of pulse width modulation
- each channel has an optional automatic low pass filter, or can be sent to one of two manually controllable filters - each channel has an optional automatic low pass filter, or can be sent to one of two manually controllable filters
- each channel can select between a narrow and a wide stereo positioning. The two stereo positions of each channel are fixed. - each channel can select between a narrow and a wide stereo positioning. The two stereo positions of each channel are fixed.
- optional ring modulation
This function requires 1024 bytes of working memory, the first 32 bytes of which are interpreted as the sound registers. This function requires 1024 bytes of working memory, the first 32 bytes of which are interpreted as the sound registers.
The base address of its working memory can be configured by writing the address to 0x12c78. It defaults to 0x00050. The base address of its working memory can be configured by writing the address to 0x12c78. It defaults to 0x00050.

File diff suppressed because one or more lines are too long

View File

@@ -91,7 +91,6 @@ 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 {
@@ -261,7 +260,6 @@ 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 start_time = Instant::now();
@@ -270,10 +268,8 @@ impl super::Runtime for MicroW8 {
device.build_output_stream( device.build_output_stream(
&config, &config,
move |buffer: &mut [f32], _| { move |buffer: &mut [f32], _| {
if let Ok(mut regs) = rx.try_recv() { if let Ok(regs) = rx.try_recv() {
memory.write(&mut store, 80, &regs).unwrap(); memory.write(&mut store, 80, &regs).unwrap();
memory.read(&mut store, 0x12c80, &mut regs).unwrap();
back_tx.send(regs).unwrap();
} }
{ {
@@ -293,11 +289,7 @@ impl super::Runtime for MicroW8 {
)? )?
}; };
Uw8Sound { Uw8Sound { stream, tx }
stream,
tx,
rx: back_rx,
}
}; };
sound.stream.play()?; sound.stream.play()?;
@@ -319,13 +311,6 @@ 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, &regs)
.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;

View File

@@ -6,10 +6,7 @@ class APU extends AudioWorkletProcessor {
this.port.onmessage = (ev) => { this.port.onmessage = (ev) => {
if(this.memory) { if(this.memory) {
if(isNaN(ev.data)) { if(isNaN(ev.data)) {
let data = U8(ev.data); U8(this.memory.buffer, 80, 32).set(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 { } else {
this.startTime = ev.data; this.startTime = ev.data;
} }

View File

@@ -211,13 +211,7 @@ export default function MicroW8(screen, config = {}) {
let platform_data = await loadModuleURL(platformUrl); let platform_data = await loadModuleURL(platformUrl);
audioNode.port.onmessage = (e) => { audioNode.port.onmessage = (e) => updateAudioReady(e.data);
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);