From 18fad499c574ca970f3e2003edabf2e64e2592b2 Mon Sep 17 00:00:00 2001 From: Skyler Lehmkuhl Date: Fri, 31 Jan 2025 06:44:03 -0500 Subject: [PATCH] Automatically resize audio buffer to prevent overruns --- lightningbeam-core/Cargo.lock | 171 +++++++----- lightningbeam-core/Cargo.toml | 11 +- lightningbeam-core/src/audio.rs | 336 +++++++++++++++++++----- lightningbeam-core/src/lib.rs | 155 +++++++---- src/pkg/lightningbeam_core.d.ts | 4 +- src/pkg/lightningbeam_core.js | 106 ++++++-- src/pkg/lightningbeam_core_bg.wasm | Bin 137320 -> 168521 bytes src/pkg/lightningbeam_core_bg.wasm.d.ts | 4 +- 8 files changed, 598 insertions(+), 189 deletions(-) diff --git a/lightningbeam-core/Cargo.lock b/lightningbeam-core/Cargo.lock index c2984ce..8740cb0 100644 --- a/lightningbeam-core/Cargo.lock +++ b/lightningbeam-core/Cargo.lock @@ -45,6 +45,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "atomic_refcell" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" + [[package]] name = "autocfg" version = "1.4.0" @@ -211,6 +217,21 @@ dependencies = [ "windows", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "dasp_sample" version = "0.11.0" @@ -244,24 +265,45 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -[[package]] -name = "hound" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" - [[package]] name = "indexmap" version = "2.7.1" @@ -349,12 +391,14 @@ name = "lightningbeam-core" version = "0.1.0" dependencies = [ "anyhow", + "atomic_refcell", "console_error_panic_hook", "cpal", - "hound", + "crossbeam-channel", + "gloo-timers", "js-sys", "log", - "minimp3", + "parking_lot", "rubato", "serde", "symphonia", @@ -362,6 +406,17 @@ dependencies = [ "wasm-bindgen-futures", "wasm-logger", "web-sys", + "web-time", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", ] [[package]] @@ -370,15 +425,6 @@ version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - [[package]] name = "mach2" version = "0.4.2" @@ -400,26 +446,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "minimp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" -dependencies = [ - "minimp3-sys", - "slice-deque", - "thiserror", -] - -[[package]] -name = "minimp3-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" -dependencies = [ - "cc", -] - [[package]] name = "ndk" version = "0.8.0" @@ -547,6 +573,29 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -599,6 +648,15 @@ dependencies = [ "rustfft", ] +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "regex" version = "1.11.1" @@ -676,6 +734,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.217" @@ -703,15 +767,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "slice-deque" -version = "0.3.0" +name = "smallvec" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" -dependencies = [ - "libc", - "mach", - "winapi", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "strength_reduce" @@ -1087,21 +1146,15 @@ dependencies = [ ] [[package]] -name = "winapi" -version = "0.3.9" +name = "web-time" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "js-sys", + "wasm-bindgen", ] -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -1111,12 +1164,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows" version = "0.54.0" diff --git a/lightningbeam-core/Cargo.toml b/lightningbeam-core/Cargo.toml index ca67190..3eb80d5 100644 --- a/lightningbeam-core/Cargo.toml +++ b/lightningbeam-core/Cargo.toml @@ -15,18 +15,19 @@ wasm-logger = "0.2" log = "0.4" rubato = "0.14.0" symphonia = { version = "0.5", features = ["all"] } +crossbeam-channel = "0.5.4" +atomic_refcell = "0.1.13" # WASM-compatible atomic refcell +parking_lot = "0.12" [dependencies.web-sys] version = "0.3.22" -features = ["console", "AudioContext"] - -[target.'cfg(not(target_arch = "wasm32"))'.dependencies] -minimp3 = "0.5.1" # Only include minimp3 for native platforms -hound = "3.5.1" # Only include hound for native platforms +features = ["console", "AudioContext", "Window", "Performance", "PerformanceTiming"] [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen-futures = "0.4" js-sys = "0.3" +web-time = "0.2" # WASM-compatible timing +gloo-timers = { version = "0.2", features = ["futures"] } # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires diff --git a/lightningbeam-core/src/audio.rs b/lightningbeam-core/src/audio.rs index 3904192..92d157d 100644 --- a/lightningbeam-core/src/audio.rs +++ b/lightningbeam-core/src/audio.rs @@ -2,18 +2,35 @@ use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::{Sample}; use std::sync::{Arc, Mutex}; use crate::{TrackManager, Timestamp, Duration, SampleCount, AudioOutput, PlaybackState}; +#[cfg(target_arch = "wasm32")] +use web_time::{Instant, Duration as StdDuration}; +#[cfg(not(target_arch = "wasm32"))] +use std::time::{Instant, Duration as StdDuration}; +use std::sync::atomic::Ordering; +use std::sync::atomic::AtomicU32; +use std::cell::Cell; +use std::collections::VecDeque; -#[derive(PartialEq)] +#[derive(PartialEq, Clone)] enum AudioState { - Suspended, - Running, + Suspended, + Running, } -// #[cfg(feature = "wasm")] -// use wasm_bindgen::prelude::*; +const DELAY_HISTORY_SIZE: usize = 5; + +#[derive(Default)] +struct StutterDetector { + delay_history: Mutex>, + desired_buffer_size: AtomicU32, + current_buffer_size: AtomicU32, + max_buffer_size: AtomicU32, + stutter_count: AtomicU32, + max_stutter_count: AtomicU32, + last_callback_time: Cell>, + scheduling_threshold: AtomicU32, +} -// #[cfg(feature="wasm")] -// #[wasm_bindgen] pub struct CpalAudioOutput { track_manager: Option>>, _stream: Option, @@ -22,12 +39,32 @@ pub struct CpalAudioOutput { timestamp: Arc>, chunk_size: usize, sample_rate: u32, + stutter_detector: Arc>, + resize_sender: crossbeam_channel::Sender<()>, // Or other channel implementation + resize_receiver: crossbeam_channel::Receiver<()>, +} + +impl StutterDetector { + fn new() -> Self { + Self { + delay_history: Mutex::new(VecDeque::with_capacity(DELAY_HISTORY_SIZE)), + desired_buffer_size: AtomicU32::new(256), + current_buffer_size: AtomicU32::new(256), + max_buffer_size: AtomicU32::new(8192), + stutter_count: AtomicU32::new(0), + max_stutter_count: AtomicU32::new(3), + last_callback_time: Cell::new(None), + scheduling_threshold: AtomicU32::new(1200), // 1.2 stored in fixed point + } + } + fn get_scheduling_threshold(&self) -> f32 { + self.scheduling_threshold.load(Ordering::Relaxed) as f32 / 1000.0 + } } -// #[cfg(feature="wasm")] -// #[wasm_bindgen] impl CpalAudioOutput { pub fn new() -> Self { + let (tx, rx) = crossbeam_channel::bounded(1); Self { track_manager: None, _stream: None, @@ -35,7 +72,10 @@ impl CpalAudioOutput { audio_state: AudioState::Suspended, timestamp: Arc::new(Mutex::new(Timestamp::from_seconds(0.0))), chunk_size: 0, - sample_rate: 44100, // Default sample rate, updated later + sample_rate: 44100, + stutter_detector: Arc::new(Mutex::new(StutterDetector::new())), + resize_sender: tx, + resize_receiver: rx, } } @@ -43,70 +83,213 @@ impl CpalAudioOutput { &mut self, device: &cpal::Device, config: cpal::SupportedStreamConfig, -) -> Result -where - T: Sample + From + cpal::SizedSample, -{ + ) -> Result + where + T: Sample + From + cpal::SizedSample, + { let supported_config = config.config(); self.sample_rate = supported_config.sample_rate.0; - let num_channels = supported_config.channels as usize; // Get channel count - + let num_channels = supported_config.channels as usize; + + let stutter_detector = self.stutter_detector.clone(); + let resize_sender = self.resize_sender.clone(); + let sample_rate = self.sample_rate; + let buffer_size_range = match config.buffer_size() { cpal::SupportedBufferSize::Range { min, max } => (*min, *max), - cpal::SupportedBufferSize::Unknown => { - // Use a reasonable default range if the device doesn't specify - (256, 4096) - } - }; - - // Define the desired buffer size and clamp it to the supported range - let desired_buffer_size = 2048; + cpal::SupportedBufferSize::Unknown => (256, 4096), + }; + + let detector_guard = self.stutter_detector.lock().unwrap(); + let desired_buffer_size = detector_guard.desired_buffer_size.load(Ordering::Relaxed); + drop(detector_guard); + let clamped_buffer_size = desired_buffer_size.clamp(buffer_size_range.0, buffer_size_range.1); - let mut stream_config = supported_config.clone(); stream_config.buffer_size = cpal::BufferSize::Fixed(clamped_buffer_size); - + + log::info!("Starting stream with buffer size {}", clamped_buffer_size); + let track_manager = self.track_manager.clone(); let timestamp = self.timestamp.clone(); - let sample_rate = self.sample_rate; - - let err_fn = |err| eprintln!("Audio stream error: {:?}", err); - + + let err_fn = |err| log::error!("Audio stream error: {:?}", err); + let stream = device.build_output_stream( - &stream_config, - move |data: &mut [T], _: &cpal::OutputCallbackInfo| { - if let Some(track_manager) = &track_manager { - let num_frames = data.len() / num_channels; // Stereo: divide by 2 - let sample_count = SampleCount::new(num_frames); - let chunk_duration = Duration::new(num_frames as f64 / sample_rate as f64); - - let mut track_manager = track_manager.lock().unwrap(); - - let mut timestamp_guard = timestamp.lock().unwrap(); - let timestamp = &mut *timestamp_guard; - - let chunk = track_manager.update_audio( - timestamp.clone(), - sample_count, - sample_rate, - ); - - // Write samples (interleaved stereo) - for (i, frame) in chunk.iter().enumerate() { - let sample = T::from(*frame); - data[i * num_channels] = sample; // Left channel - data[i * num_channels + 1] = sample; // Right channel (or process separately) + &stream_config, + move |data: &mut [T], _: &cpal::OutputCallbackInfo| { + // Timing measurement + let processing_start = if cfg!(target_arch = "wasm32") { + let perf = web_sys::window() + .and_then(|w| w.performance()) + .expect("performance should be available"); + let now_ms = perf.now(); + Instant::now() + StdDuration::from_secs_f64(now_ms / 1000.0) + } else { + Instant::now() + }; + + // Initialize resize flag outside of lock scope + let mut should_resize = false; + let current_size; + let buffer_duration; + let scheduling_threshold; + + { + let detector = stutter_detector.lock().unwrap(); + + // Update detector state + current_size = detector.current_buffer_size.load(Ordering::Relaxed); + buffer_duration = StdDuration::from_secs_f64(current_size as f64 / sample_rate as f64); + scheduling_threshold = detector.get_scheduling_threshold(); + + // Calculate scheduling delay + let last_time = detector.last_callback_time.get(); + // log::info!("Current size: {}", current_size); + + // Audio processing + if let Some(track_manager) = &track_manager { + let num_frames = data.len() / num_channels; // Stereo: divide by 2 + let sample_count = SampleCount::new(num_frames); + let chunk_duration = Duration::new(num_frames as f64 / sample_rate as f64); + + let mut track_manager = track_manager.lock().unwrap(); + + let mut timestamp_guard = timestamp.lock().unwrap(); + let timestamp = &mut *timestamp_guard; + + let chunk = track_manager.update_audio( + timestamp.clone(), + sample_count, + sample_rate, + ); + + // Write samples (interleaved stereo) + for (i, frame) in chunk.iter().enumerate() { + let sample = T::from(*frame); + for channel in 0..num_channels { + let index = i * num_channels + channel; + if index < data.len() { + data[index] = sample; } - - *timestamp_guard += chunk_duration; + } } - }, - err_fn, - None, + + *timestamp_guard += chunk_duration; + + // Stutter detection logic + let processing_time = processing_start.elapsed(); + let processing_overrun = processing_time > buffer_duration; + + // Update delay history + if let Some(last) = last_time { + let interval = processing_start.duration_since(last); + let mut history = detector.delay_history.lock().unwrap(); + if history.len() >= 5 { + history.pop_front(); + } + history.push_back(interval); + // log::info!("Interval: {:?}", interval); + } + + // Calculate average delay + let avg_delay = { + let history = detector.delay_history.lock().unwrap(); + if history.is_empty() { + StdDuration::ZERO + } else { + history.iter().sum::() / history.len() as u32 + } + }; + + // log::info!("Average delay: {:?}", avg_delay); + + // Determine stutter + let stutter_detected = avg_delay > buffer_duration.mul_f32(scheduling_threshold) + || processing_overrun; + + // Update stutter count with hysteresis + let current_count = detector.stutter_count.load(Ordering::Relaxed); + if stutter_detected { + detector.stutter_count.store( + (current_count + 1).min(detector.max_stutter_count.load(Ordering::Relaxed)), + Ordering::Relaxed + ); + } else { + detector.stutter_count.store( + current_count.saturating_sub(1), + Ordering::Relaxed + ); + } + + // Check for resize + if detector.stutter_count.load(Ordering::Relaxed) >= detector.max_stutter_count.load(Ordering::Relaxed) { + let desired_size = detector.desired_buffer_size.load(Ordering::Relaxed); + let new_size = (desired_size * 2).min(detector.max_buffer_size.load(Ordering::Relaxed)); + + if new_size != desired_size { + detector.desired_buffer_size.store(new_size, Ordering::Relaxed); + detector.stutter_count.store(0, Ordering::Relaxed); + should_resize = true; + } + } + } + + detector.last_callback_time.set(Some(processing_start)); + } + + // Send resize request outside of lock + if should_resize { + let _ = resize_sender.try_send(()); + } + }, + err_fn, + None, )?; + // Update current buffer size after stream creation + let detector = self.stutter_detector.lock().unwrap(); + detector.current_buffer_size.store(clamped_buffer_size, Ordering::Relaxed); + Ok(stream) } + + fn recreate_stream(&mut self) -> Result<(), Box> { + // Stop and destroy old stream first + if let Some(old_stream) = self._stream.take() { + old_stream.pause()?; + // Explicitly drop the stream + drop(old_stream); + } + + // Add a small delay to ensure resources are freed (especially important in WASM) + #[cfg(not(target_arch = "wasm32"))] + std::thread::sleep(std::time::Duration::from_millis(50)); + + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen_futures::spawn_local; + use gloo_timers::future::sleep; + spawn_local(async { + sleep(std::time::Duration::from_millis(50)).await; + }); + } + + // Recreate stream with current configuration + let host = cpal::default_host(); + let device = host.default_output_device() + .ok_or_else(|| "No output device available")?; + let supported_config = device.default_output_config()?; + + self._stream = Some(self.build_stream::(&device, supported_config)?); + + // Restart playback if needed + if self.audio_state == AudioState::Running { + self._stream.as_ref().unwrap().play()?; + } + + Ok(()) +} } impl AudioOutput for CpalAudioOutput { @@ -128,7 +311,7 @@ impl AudioOutput for CpalAudioOutput { fn stop(&mut self) { self.playback_state = PlaybackState::Stopped; } - + fn resume(&mut self) -> Result<(), anyhow::Error> { if self.audio_state == AudioState::Suspended { if let Some(stream) = &self._stream { @@ -150,4 +333,37 @@ impl AudioOutput for CpalAudioOutput { fn set_chunk_size(&mut self, chunk_size: usize) { self.chunk_size = chunk_size } -} + fn check_resize(&mut self) -> Result<(), Box> { + // Process resize requests with timeout + let timeout = StdDuration::from_millis(10); + while let Ok(()) = self.resize_receiver.try_recv() { + let start = Instant::now(); + + // Try to lock, non-blocking + { + let detector = match self.stutter_detector.try_lock() { + Ok(d) => d, + Err(_) => { + // Couldn't acquire lock immediately, skip this iteration + return Ok(()); + } + }; + + // Quick check before heavy operation + if detector.desired_buffer_size.load(Ordering::Relaxed) == detector.current_buffer_size.load(Ordering::Relaxed) { + continue; + } + detector.current_buffer_size.store(detector.desired_buffer_size.load(Ordering::Relaxed), Ordering::Relaxed); + } + + // Actual stream recreation + log::info!("Restarting stream"); + let _ = self.recreate_stream()?; + + if Instant::now().duration_since(start) > timeout { + break; + } + } + Ok(()) + } +} \ No newline at end of file diff --git a/lightningbeam-core/src/lib.rs b/lightningbeam-core/src/lib.rs index 227d597..de745fd 100644 --- a/lightningbeam-core/src/lib.rs +++ b/lightningbeam-core/src/lib.rs @@ -124,6 +124,7 @@ pub trait AudioOutput { fn register_track_manager(&mut self, track_manager: Arc>); fn get_timestamp(&mut self) -> Timestamp; fn set_chunk_size(&mut self, chunk_size: usize); + fn check_resize(&mut self) -> Result<(), Box>; } pub trait FrameTarget { @@ -372,64 +373,64 @@ fn decode_audio( ) -> Result<(), Box> { // Create a media source from the byte slice let mss = MediaSourceStream::new( - Box::new(Cursor::new(audio_data.to_vec())), - Default::default(), + Box::new(Cursor::new(audio_data.to_vec())), + Default::default(), ); - + // Use a fresh hint (no extension specified) for format detection let hint = Hint::new(); - + // Probe the media source for a supported format let probed = symphonia::default::get_probe() - .format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())?; - + .format(&hint, mss, &FormatOptions::default(), &MetadataOptions::default())?; + // Get the format reader let mut format = probed.format; - + // Find the first supported audio track let default_track = format - .tracks() - .iter() - .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL) - .ok_or("No supported audio track found")?; - + .tracks() + .iter() + .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL) + .ok_or("No supported audio track found")?; + // Create a decoder for the track let mut decoder = symphonia::default::get_codecs() - .make(&default_track.codec_params, &DecoderOptions::default())?; - + .make(&default_track.codec_params, &DecoderOptions::default())?; + // Get the sample rate from the track let sample_rate = default_track.codec_params.sample_rate.ok_or("Unknown sample rate")?; let mut decoded_samples = Vec::new(); - + // Decode loop loop { - let packet = match format.next_packet() { - Ok(packet) => packet, - Err(_) => break, // End of stream - }; - - match decoder.decode(&packet)? { - AudioBufferRef::F32(buf) => { - for i in 0..buf.frames() { - for c in 0..buf.spec().channels.count() { - decoded_samples.push(buf.chan(c)[i]); - } - } + let packet = match format.next_packet() { + Ok(packet) => packet, + Err(_) => break, // End of stream + }; + + match decoder.decode(&packet)? { + AudioBufferRef::F32(buf) => { + for i in 0..buf.frames() { + for c in 0..buf.spec().channels.count() { + decoded_samples.push(buf.chan(c)[i]); } - AudioBufferRef::S16(buf) => { - for i in 0..buf.frames() { - for c in 0..buf.spec().channels.count() { - decoded_samples.push(buf.chan(c)[i] as f32 / 32768.0); - } - } - } - _ => return Err("Unsupported audio format".into()), + } } + AudioBufferRef::S16(buf) => { + for i in 0..buf.frames() { + for c in 0..buf.spec().channels.count() { + decoded_samples.push(buf.chan(c)[i] as f32 / 32768.0); + } + } + } + _ => return Err("Unsupported audio format".into()), + } } - + // Add the decoded audio to the track track.add_buffer(start_time, sample_rate, decoded_samples); - + Ok(()) } @@ -469,7 +470,11 @@ pub struct CoreInterface { #[wasm_bindgen(skip)] track_manager: Arc>, #[wasm_bindgen(skip)] - cpal_audio_output: Box, + cpal_audio_output: Arc>, + #[wasm_bindgen(skip)] + resize_interval_id: Option, + #[wasm_bindgen(skip)] + resize_closure: Option>, } #[cfg(feature="wasm")] @@ -479,14 +484,21 @@ impl CoreInterface { pub fn new() -> Self { Self { track_manager: Arc::new(Mutex::new(TrackManager::new())), - cpal_audio_output: Box::new(CpalAudioOutput::new()) + cpal_audio_output: Arc::new(Mutex::new(CpalAudioOutput::new())), + resize_interval_id: None, + resize_closure: None, } } pub fn init(&mut self) { println!("Init CoreInterface"); - let track_manager_clone = self.track_manager.clone(); - self.cpal_audio_output.register_track_manager(track_manager_clone); - let _ = self.cpal_audio_output.start(); + { + let track_manager_clone = self.track_manager.clone(); + let mut cpal_audio_output = self.cpal_audio_output.lock().unwrap(); + cpal_audio_output.register_track_manager(track_manager_clone); + let _ = cpal_audio_output.start(); + } + + self.start_resize_polling(); } pub fn play(&mut self, timestamp: f64) { // Lock the Mutex to get access to TrackManager @@ -500,9 +512,52 @@ impl CoreInterface { } pub fn resume_audio(&mut self) -> Result<(), JsValue> { // Call this on user gestures if audio gets suspended - self.cpal_audio_output.resume() + self.cpal_audio_output.lock().unwrap().resume() .map_err(|e| JsValue::from_str(&format!("Failed to resume audio: {}", e))) } + // In CoreInterface + fn start_resize_polling(&mut self) { + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen::{prelude::*, JsCast}; + use js_sys::Array; + + let window = web_sys::window().unwrap(); + let audio_output = Arc::clone(&self.cpal_audio_output); + + // Use weak reference to break cycle + let weak_audio = Arc::downgrade(&audio_output); + let closure = Closure::::new(move || { + if let Some(audio) = weak_audio.upgrade() { + // NON-BLOCKING lock attempt + if let Ok(mut audio) = audio.try_lock() { + let _ = audio.check_resize(); + } + } + }); + + let args = Array::new(); + let interval_id = window + .set_interval_with_callback_and_timeout_and_arguments( + closure.as_ref().unchecked_ref(), + 50, + &args + ) + .unwrap(); + + self.resize_interval_id = Some(interval_id); + self.resize_closure = Some(closure); + } + + #[cfg(not(target_arch = "wasm32"))] + { + let mut audio = self.cpal_audio_output.clone(); + std::thread::spawn(move || loop { + let _ = audio.check_resize(); + std::thread::sleep(std::time::Duration::from_millis(50)); + }); + } + } pub fn add_sine_track(&mut self, frequency: f32) -> Result<(), String> { if frequency.is_nan() || frequency.is_infinite() || frequency <= 0.0 { return Err(format!("Invalid frequency: {}", frequency)); @@ -516,7 +571,7 @@ impl CoreInterface { } pub fn get_timestamp(&mut self) -> f64 { - self.cpal_audio_output.get_timestamp().as_seconds() + self.cpal_audio_output.lock().unwrap().get_timestamp().as_seconds() } pub fn get_tracks(&mut self) -> Vec { let track_manager = self.track_manager.lock().unwrap(); @@ -528,8 +583,20 @@ impl CoreInterface { }) .collect() } + } +// Cleanup implementation +#[cfg(feature = "wasm")] +impl Drop for CoreInterface { + fn drop(&mut self) { + if let Some(interval_id) = self.resize_interval_id { + web_sys::window() + .unwrap() + .clear_interval_with_handle(interval_id); + } + } +} struct PlainTextLogger; diff --git a/src/pkg/lightningbeam_core.d.ts b/src/pkg/lightningbeam_core.d.ts index 3b8c0e8..91bd9d3 100644 --- a/src/pkg/lightningbeam_core.d.ts +++ b/src/pkg/lightningbeam_core.d.ts @@ -42,7 +42,9 @@ export interface InitOutput { readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_add_to_stack_pointer: (a: number) => number; readonly __wbindgen_free: (a: number, b: number, c: number) => void; - readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b: (a: number, b: number) => void; + readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h078d17eff0b70a99: (a: number, b: number) => void; + readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h26b4819ece79f796: (a: number, b: number) => void; + readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb1f2a4138d993283: (a: number, b: number, c: number) => void; readonly __wbindgen_start: () => void; } diff --git a/src/pkg/lightningbeam_core.js b/src/pkg/lightningbeam_core.js index 1df0b89..42bafa0 100644 --- a/src/pkg/lightningbeam_core.js +++ b/src/pkg/lightningbeam_core.js @@ -26,6 +26,18 @@ function handleError(f, args) { } } +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + let cachedFloat32ArrayMemory0 = null; function getFloat32ArrayMemory0() { @@ -62,18 +74,6 @@ function isLikeNone(x) { return x === undefined || x === null; } -function dropObject(idx) { - if (idx < 132) return; - heap[idx] = heap_next; - heap_next = idx; -} - -function takeObject(idx) { - const ret = getObject(idx); - dropObject(idx); - return ret; -} - const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(state => { @@ -249,8 +249,16 @@ export function main_js() { wasm.main_js(); } -function __wbg_adapter_18(arg0, arg1) { - wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b(arg0, arg1); +function __wbg_adapter_20(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h078d17eff0b70a99(arg0, arg1); +} + +function __wbg_adapter_23(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h26b4819ece79f796(arg0, arg1); +} + +function __wbg_adapter_26(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb1f2a4138d993283(arg0, arg1, addHeapObject(arg2)); } const CoreInterfaceFinalization = (typeof FinalizationRegistry === 'undefined') @@ -445,6 +453,13 @@ function __wbg_get_imports() { const ret = getObject(arg0).call(getObject(arg1)); return addHeapObject(ret); }, arguments) }; + imports.wbg.__wbg_clearInterval_ad2594253cc39c4b = function(arg0, arg1) { + getObject(arg0).clearInterval(arg1); + }; + imports.wbg.__wbg_clearTimeout_96804de0ab838f26 = function(arg0) { + const ret = clearTimeout(takeObject(arg0)); + return addHeapObject(ret); + }; imports.wbg.__wbg_close_5a97ef05b337f8ce = function() { return handleError(function (arg0) { const ret = getObject(arg0).close(); return addHeapObject(ret); @@ -501,6 +516,10 @@ function __wbg_get_imports() { const ret = new Object(); return addHeapObject(ret); }; + imports.wbg.__wbg_new_78feb108b6472713 = function() { + const ret = new Array(); + return addHeapObject(ret); + }; imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { const ret = new Function(getStringFromWasm0(arg0, arg1)); return addHeapObject(ret); @@ -509,10 +528,45 @@ function __wbg_get_imports() { const ret = new lAudioContext(getObject(arg0)); return addHeapObject(ret); }, arguments) }; + imports.wbg.__wbg_now_6f91d421b96ea22a = function(arg0) { + const ret = getObject(arg0).now(); + return ret; + }; + imports.wbg.__wbg_now_d18023d54d4e5500 = function(arg0) { + const ret = getObject(arg0).now(); + return ret; + }; + imports.wbg.__wbg_performance_c185c0cdc2766575 = function(arg0) { + const ret = getObject(arg0).performance; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_performance_f71bd4abe0370171 = function(arg0) { + const ret = getObject(arg0).performance; + return addHeapObject(ret); + }; + imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) { + queueMicrotask(getObject(arg0)); + }; + imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) { + const ret = getObject(arg0).queueMicrotask; + return addHeapObject(ret); + }; + imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; imports.wbg.__wbg_resume_35efdc4ffe13bf18 = function() { return handleError(function (arg0) { const ret = getObject(arg0).resume(); return addHeapObject(ret); }, arguments) }; + imports.wbg.__wbg_setInterval_83d54331ceeda644 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).setInterval(getObject(arg1), arg2, ...getObject(arg3)); + return ret; + }, arguments) }; + imports.wbg.__wbg_setTimeout_eefe7f4c234b0c6b = function() { return handleError(function (arg0, arg1) { + const ret = setTimeout(getObject(arg0), arg1); + return addHeapObject(ret); + }, arguments) }; imports.wbg.__wbg_setTimeout_f2fe5af8e3debeb3 = function() { return handleError(function (arg0, arg1, arg2) { const ret = getObject(arg0).setTimeout(getObject(arg1), arg2); return ret; @@ -548,6 +602,14 @@ function __wbg_get_imports() { const ret = typeof window === 'undefined' ? null : window; return isLikeNone(ret) ? 0 : addHeapObject(ret); }; + imports.wbg.__wbg_suspend_6011a41599f07de4 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).suspend(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; imports.wbg.__wbindgen_boolean_get = function(arg0) { const v = getObject(arg0); const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; @@ -562,8 +624,16 @@ function __wbg_get_imports() { const ret = false; return ret; }; - imports.wbg.__wbindgen_closure_wrapper151 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 73, __wbg_adapter_18); + imports.wbg.__wbindgen_closure_wrapper207 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 82, __wbg_adapter_20); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper265 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 109, __wbg_adapter_23); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper283 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 116, __wbg_adapter_26); return addHeapObject(ret); }; imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { @@ -573,6 +643,10 @@ function __wbg_get_imports() { getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; imports.wbg.__wbindgen_is_undefined = function(arg0) { const ret = getObject(arg0) === undefined; return ret; diff --git a/src/pkg/lightningbeam_core_bg.wasm b/src/pkg/lightningbeam_core_bg.wasm index 2d2ab1d3a5a35baef4c0bff45a64f17356355b42..e80499dbcd8a5f2cdbc91ca3eebdcc41165815b9 100644 GIT binary patch delta 73360 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 C1LEKS diff --git a/src/pkg/lightningbeam_core_bg.wasm.d.ts b/src/pkg/lightningbeam_core_bg.wasm.d.ts index 7a3debd..882e2b7 100644 --- a/src/pkg/lightningbeam_core_bg.wasm.d.ts +++ b/src/pkg/lightningbeam_core_bg.wasm.d.ts @@ -20,5 +20,7 @@ export const __wbindgen_malloc: (a: number, b: number) => number; export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_add_to_stack_pointer: (a: number) => number; export const __wbindgen_free: (a: number, b: number, c: number) => void; -export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hfe92e343adbc229b: (a: number, b: number) => void; +export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h078d17eff0b70a99: (a: number, b: number) => void; +export const _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h26b4819ece79f796: (a: number, b: number) => void; +export const _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb1f2a4138d993283: (a: number, b: number, c: number) => void; export const __wbindgen_start: () => void;