diff options
| -rw-r--r-- | .dir-locals.el | 2 | ||||
| -rw-r--r-- | crates/teleia/src/audio.rs | 29 |
2 files changed, 19 insertions, 12 deletions
diff --git a/.dir-locals.el b/.dir-locals.el index 9a84ba1..7d26985 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -2,7 +2,7 @@ ((eglot-workspace-configuration . (:rust-analyzer ( :cargo - ( ;; :target "wasm32-unknown-unknown" + ( :target "wasm32-unknown-unknown" :targetDir t) :hover (:show (:fields 10)))))))) diff --git a/crates/teleia/src/audio.rs b/crates/teleia/src/audio.rs index 44965bb..087b63e 100644 --- a/crates/teleia/src/audio.rs +++ b/crates/teleia/src/audio.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; #[cfg(target_arch = "wasm32")] -use std::cell::RefCell; +use std::{cell::RefCell, sync::{Arc, Mutex}}; #[cfg(target_arch = "wasm32")] pub struct Context { @@ -21,33 +21,42 @@ impl Context { #[cfg(target_arch = "wasm32")] pub struct Audio { - pub buffer: &'static RefCell<Option<web_sys::AudioBuffer>>, - //pub source: &'static web_sys::AudioBufferSourceNode, + pub buffer: Arc<Mutex<Option<web_sys::AudioBuffer>>>, } #[cfg(target_arch = "wasm32")] impl Audio { pub fn new(ctx: &Context, bytes: &[u8]) -> Self { - let sbuffer: &_ = Box::leak(Box::new(RefCell::new(None))); - let sclone: &'static RefCell<Option<web_sys::AudioBuffer>> = - <&_>::clone(&sbuffer); + let sbuffer = Arc::new(Mutex::new(None)); + let sclone = sbuffer.clone(); let ret = Audio { buffer: sclone, }; let jsp = ctx.audio.decode_audio_data(&js_sys::Uint8Array::from(bytes).buffer()).expect("failed to decode audio"); let promise = wasm_bindgen_futures::JsFuture::from(jsp); - wasm_bindgen_futures::spawn_local(async { + wasm_bindgen_futures::spawn_local(async move { if let Some(data) = promise.await.ok() { - *sbuffer.borrow_mut() = Some(web_sys::AudioBuffer::from(data)); + *sbuffer.lock().unwrap() = Some(web_sys::AudioBuffer::from(data)); } () }); ret } + pub fn from_samples(ctx: &Context, sample_rate: f32, samples: &[f32]) -> Self { + let buf = ctx.audio.create_buffer(1, samples.len() as u32, sample_rate) + .expect("failed to create audio buffer"); + buf.copy_to_channel(samples, 0).expect("failed to populate audio samples"); + Audio { + buffer: Arc::new(Mutex::new(Some(buf))) + } + } + pub fn play(&self, ctx: &Context, looping: Option<(Option<f64>, Option<f64>)>) -> Option<web_sys::AudioBufferSourceNode> { let source = ctx.audio.create_buffer_source().ok()?; - source.set_buffer((&*self.buffer.borrow()).as_ref()); + if let Some(ab) = &*self.buffer.lock().unwrap() { + source.set_buffer(Some(&ab)); + } else { return None }; if let Some((ms, me)) = looping { source.set_loop(true); if let Some(s) = ms { source.set_loop_start(s) } @@ -62,9 +71,7 @@ impl Audio { #[cfg(target_arch = "wasm32")] pub struct Assets { pub ctx: Context, - pub audio: HashMap<String, Audio>, - pub music_node: Option<web_sys::AudioBufferSourceNode>, } |
