mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 19:26:43 +01:00
remove back-channel from audio thread for now
It needs some more thought before committing to it.
This commit is contained in:
@@ -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
@@ -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, ®s).unwrap();
|
memory.write(&mut store, 80, ®s).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, ®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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user