Fix audio for wasm
Some checks failed
Cargo Build & Test / Rust project - latest (stable) (push) Failing after 10s

This commit is contained in:
2026-03-27 00:49:06 -05:00
parent f6c3d073e7
commit e882b3b325
2 changed files with 74 additions and 68 deletions

View File

@@ -8,7 +8,12 @@ use nes_emu::{Break, NES};
#[cfg(not(target_arch = "wasm32"))]
use tracing_subscriber::EnvFilter;
use web_sys::{
js_sys::{Function, Uint8Array}, wasm_bindgen::{closure::Closure, Clamped, JsValue, UnwrapThrowExt}, window, AudioBuffer, AudioBufferOptions, AudioContext, AudioContextOptions, AudioContextState, CanvasRenderingContext2d, HtmlButtonElement, HtmlCanvasElement, HtmlInputElement, ImageBitmap, ImageData, KeyboardEvent
AudioBuffer, AudioBufferOptions, AudioContext, AudioContextOptions, AudioContextState,
CanvasRenderingContext2d, HtmlButtonElement, HtmlCanvasElement, HtmlInputElement, ImageBitmap,
ImageData, KeyboardEvent,
js_sys::{Function, Uint8Array},
wasm_bindgen::{Clamped, JsValue, UnwrapThrowExt, closure::Closure},
window,
};
const DEFAULT_ROM: &[u8] = include_bytes!(concat!(
@@ -209,76 +214,77 @@ pub fn main() {
if last_frame + FRAME_TIME > audio.current_time() {
last_frame += FRAME_TIME;
if audio.state() == AudioContextState::Running {
if poisoned.swap(true, Ordering::AcqRel) {
cancel = true;
// if let Some(_id) = timeout_cpy.lock().ok().and_then(|v| *v) {
if poisoned.swap(true, Ordering::AcqRel) {
cancel = true;
// if let Some(_id) = timeout_cpy.lock().ok().and_then(|v| *v) {
// win.clear_interval_with_handle(id);
// win.cancel_animation_frame(id);
info!("Cleared interval due to poison");
// } else {
// info!("Not yet set id");
// }
} else {
let mut n = nes.lock().unwrap();
// info!("Running frame");
let mut count = 0;
while !n.halted() && !n.run_one_clock_cycle(&Break::default()).ppu_frame {
count += 1;
if count > 90_000 {
info!("Loop overran");
break;
// } else {
// info!("Not yet set id");
// }
} else {
let mut n = nes.lock().unwrap();
// info!("Running frame");
let mut count = 0;
while !n.halted() && !n.run_one_clock_cycle(&Break::default()).ppu_frame {
count += 1;
if count > 90_000 {
info!("Loop overran");
break;
}
}
// info!("New samples: {}", n.apu().get_frame_samples().len());
for s in n.apu().get_frame_samples() {
// raw_audio_buffer[cur_pos] = ((*s as f32) - 127.5) / 128.;
raw_audio_buffer[cur_pos] = (*s as f32) / 256.;
cur_pos += 1;
if cur_pos == BUFFER_SIZE {
cur_pos = 0;
cur_total += BUFFER_SIZE;
if win.get("play_audio").is_some_and(|v| v.is_truthy()) {
let audio_buffer = AudioBuffer::new(&audio_buffer_opts)
.expect_throw("Failed to create audio buffer");
audio_buffer
.copy_to_channel(&raw_audio_buffer, 0)
.expect_throw("Failed to copy audio data");
// info!("S: {:?}", audio_buffer.get_channel_data(0));
let source_node = audio
.create_buffer_source()
.expect_throw("Failed to create buffer source");
// source_node.set_loop(false);
source_node.set_buffer(Some(&audio_buffer));
source_node
.connect_with_audio_node(&gain_node)
.expect_throw("Failed to connect to gain node");
source_node
.start_with_when((cur_total as f64) / SAMPLE_RATE)
.expect_throw("Failed to start source_node");
// info!(
// "At {cur_total} samples, {:02.04}s ahead !loop",
// (cur_total as f64) / SAMPLE_RATE - audio.current_time()
// );
}
}
}
n.apu_mut().reset_frame_samples(); // Discard audio samples
// info!("Completed Frame in {} cycles", count);
let data = Clamped(n.ppu().render_buffer.raw_image());
// info!("Creating bitmap");
let image = ImageData::new_with_u8_clamped_array(data, 256)
.expect_throw("Image data could not be created");
let data = win
.create_image_bitmap_with_image_data(&image)
.expect_throw("Bitmap could not be created");
let _ = data.then(&cl);
drop(n);
if !poisoned.swap(false, Ordering::AcqRel) {
panic!("Poisoned logic invalid");
}
}
info!("New samples: {}", n.apu().get_frame_samples().len());
// for s in n.apu().get_frame_samples() {
// // raw_audio_buffer[cur_pos] = ((*s as f32) - 127.5) / 128.;
// raw_audio_buffer[cur_pos] = (*s as f32) / 256.;
// cur_pos += 1;
// if cur_pos == BUFFER_SIZE {
// cur_pos = 0;
// cur_total += BUFFER_SIZE;
// let audio_buffer = AudioBuffer::new(&audio_buffer_opts)
// .expect_throw("Failed to create audio buffer");
// audio_buffer
// .copy_to_channel(&raw_audio_buffer, 0)
// .expect_throw("Failed to copy audio data");
// // info!("S: {:?}", audio_buffer.get_channel_data(0));
// let source_node = audio
// .create_buffer_source()
// .expect_throw("Failed to create buffer source");
// source_node.set_loop(true);
// source_node.set_buffer(Some(&audio_buffer));
// source_node
// .connect_with_audio_node(&gain_node)
// .expect_throw("Failed to connect to gain node");
// source_node
// .start_with_when((cur_total as f64) / SAMPLE_RATE)
// .expect_throw("Failed to start source_node");
// info!(
// "At {cur_total} samples, {:02.04}s ahead",
// (cur_total as f64) / SAMPLE_RATE - audio.current_time()
// );
// // TODO: create and play audio node
// }
// }
n.apu_mut().reset_frame_samples(); // Discard audio samples
// info!("Completed Frame in {} cycles", count);
let data = Clamped(n.ppu().render_buffer.raw_image());
// info!("Creating bitmap");
let image = ImageData::new_with_u8_clamped_array(data, 256)
.expect_throw("Image data could not be created");
let data = win
.create_image_bitmap_with_image_data(&image)
.expect_throw("Bitmap could not be created");
let _ = data.then(&cl);
drop(n);
if !poisoned.swap(false, Ordering::AcqRel) {
panic!("Poisoned logic invalid");
}
}
}
}
if !cancel {
@@ -292,8 +298,7 @@ pub fn main() {
// .set_interval_with_callback_and_timeout_and_arguments_0(&Function::from(js), 16)
// .expect_throw("Failed to setup timeout");
// let timeout_id =
win
.request_animation_frame(&js)
win.request_animation_frame(&js)
.expect_throw("Failed to setup animation frame");
*period.lock().unwrap() = Some(js);
// *timeout.lock().unwrap() = Some(timeout_id);

View File

@@ -3,4 +3,5 @@
# RUSTFLAGS=--cfg=web_sys_unstable_apis
cargo build --target wasm32-unknown-unknown --bin wasm --features web --release || exit
wasm-bindgen target/wasm32-unknown-unknown/release/wasm.wasm --out-dir wasm --web || exit
scp wasm/* hpdl380g10.loadingm.xyz:/data/site/nes/
simple-http-server wasm || exit