From b880fee8e7c21531d167619b8b60139cd03567d2 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Sat, 22 Jan 2022 05:08:53 +0100 Subject: [PATCH] Switch to upsteam cpal and avoid creating unnecessary threads --- Cargo.toml | 3 +- src/framework/backend_glutin.rs | 4 ++ src/framework/backend_sdl2.rs | 4 +- src/sound/mod.rs | 73 ++++++++++++++++----------------- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ce06037..ee20ba0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ exe = [] android = [] [dependencies] -#cpal = { path = "./3rdparty/cpal" } #glutin = { path = "./3rdparty/glutin/glutin", optional = true } #lua-ffi = { path = "./3rdparty/luajit-rs", optional = true } #winit = { path = "./3rdparty/winit", optional = true, default_features = false, features = ["x11"] } @@ -54,7 +53,7 @@ bitvec = "0.20" byteorder = "1.4" case_insensitive_hashmap = "1.0.0" chrono = "0.4" -cpal = { git = "https://github.com/doukutsu-rs/cpal.git", rev = "4218ff23242834d36bcdcc0c2e3883985c15b5e0" } +cpal = "0.13" directories = "3" downcast = "0.11" funty = "=1.1.0" # https://github.com/bitvecto-rs/bitvec/issues/105 diff --git a/src/framework/backend_glutin.rs b/src/framework/backend_glutin.rs index 6be5a1b..2b1e240 100644 --- a/src/framework/backend_glutin.rs +++ b/src/framework/backend_glutin.rs @@ -176,6 +176,8 @@ impl BackendEventLoop for GlutinEventLoop { request_android_redraw(); } } + + state_ref.sound_manager.resume(); } Event::Suspended => { { @@ -187,6 +189,8 @@ impl BackendEventLoop for GlutinEventLoop { unsafe { window.surface_destroyed(); } + + state_ref.sound_manager.pause(); } Event::WindowEvent { event: WindowEvent::Resized(size), window_id } if window_id == window.window().id() => diff --git a/src/framework/backend_sdl2.rs b/src/framework/backend_sdl2.rs index ae3f31d..0bc3bbb 100644 --- a/src/framework/backend_sdl2.rs +++ b/src/framework/backend_sdl2.rs @@ -168,11 +168,14 @@ impl BackendEventLoop for SDL2EventLoop { *mutex = false; } + state.sound_manager.resume(); game.loops = 0; } WindowEvent::FocusLost | WindowEvent::Hidden => { let mut mutex = GAME_SUSPENDED.lock().unwrap(); *mutex = true; + + state.sound_manager.pause(); } WindowEvent::SizeChanged(width, height) => { ctx.screen_size = (width.max(1) as f32, height.max(1) as f32); @@ -267,7 +270,6 @@ impl BackendEventLoop for SDL2EventLoop { refs.video.gl_get_proc_address(name) as *const _ }; - // log::info!("gl proc {} -> {:?}", name, result); *user_data = Rc::into_raw(refs) as *mut c_void; result diff --git a/src/sound/mod.rs b/src/sound/mod.rs index fc14596..48da74a 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -41,6 +41,7 @@ pub struct SoundManager { prev_song_id: usize, current_song_id: usize, no_audio: bool, + stream: Option, } enum SongFormat { @@ -67,7 +68,13 @@ impl SoundManager { if ctx.headless { log::info!("Running in headless mode, skipping initialization."); - return Ok(SoundManager { tx: tx.clone(), prev_song_id: 0, current_song_id: 0, no_audio: true }); + return Ok(SoundManager { + tx: tx.clone(), + prev_song_id: 0, + current_song_id: 0, + no_audio: true, + stream: None, + }); } let host = cpal::default_host(); @@ -76,18 +83,29 @@ impl SoundManager { let config = device.default_output_config()?; let bnk = wave_bank::SoundBank::load_from(filesystem::open(ctx, "/builtin/organya-wavetable-doukutsu.bin")?)?; + let res = match config.sample_format() { + cpal::SampleFormat::F32 => run::(rx, bnk, device, config.into()), + cpal::SampleFormat::I16 => run::(rx, bnk, device, config.into()), + cpal::SampleFormat::U16 => run::(rx, bnk, device, config.into()), + }; - std::thread::spawn(move || { - if let Err(err) = match config.sample_format() { - cpal::SampleFormat::F32 => run::(rx, bnk, &device, &config.into()), - cpal::SampleFormat::I16 => run::(rx, bnk, &device, &config.into()), - cpal::SampleFormat::U16 => run::(rx, bnk, &device, &config.into()), - } { - log::error!("Something went wrong in audio thread: {}", err); - } - }); + if let Err(res) = &res { + log::error!("Error initializing audio: {}", res); + } - Ok(SoundManager { tx: tx.clone(), prev_song_id: 0, current_song_id: 0, no_audio: false }) + Ok(SoundManager { tx: tx.clone(), prev_song_id: 0, current_song_id: 0, no_audio: false, stream: res.ok() }) + } + + pub fn pause(&mut self) { + if let Some(stream) = &mut self.stream { + let _ = stream.pause(); + } + } + + pub fn resume(&mut self) { + if let Some(stream) = &mut self.stream { + let _ = stream.play(); + } } pub fn play_sfx(&self, id: u8) { @@ -367,7 +385,7 @@ impl SoundManager { } } -enum PlaybackMessage { +pub(in crate::sound) enum PlaybackMessage { Stop, PlayOrganyaSong(Box), #[cfg(feature = "ogg-playback")] @@ -408,9 +426,9 @@ impl Default for PlaybackStateType { fn run( rx: Receiver, bank: SoundBank, - device: &cpal::Device, - config: &cpal::StreamConfig, -) -> GameResult + device: cpal::Device, + config: cpal::StreamConfig, +) -> GameResult where T: cpal::Sample, { @@ -444,7 +462,7 @@ where let err_fn = |err| eprintln!("an error occurred on stream: {}", err); let stream = device.build_output_stream( - config, + &config, move |data: &mut [T], _: &cpal::OutputCallbackInfo| { loop { match rx.try_recv() { @@ -456,7 +474,7 @@ where org_engine.start_song(*song, &bank); for i in &mut bgm_buf[0..samples] { - *i = 0x8080 + *i = 0x8000 } samples = org_engine.render_to(&mut bgm_buf); bgm_index = 0; @@ -651,24 +669,5 @@ where stream.play()?; - let mut saved_state = true; - loop { - std::thread::sleep(Duration::from_millis(10)); - - { - let mutex = crate::GAME_SUSPENDED.lock().unwrap(); - let state = *mutex; - if saved_state != state { - saved_state = state; - - if state { - if let Err(e) = stream.pause() { - log::error!("Failed to pause the stream: {:?}", e); - } - } else if let Err(e) = stream.play() { - log::error!("Failed to unpause the stream: {:?}", e); - } - } - } - } + Ok(stream) }