fix: audio sounds now overlap instead of queueing sequentially

Each sound creates its own Sink via OutputStreamHandle and calls detach(),
so sounds play simultaneously and self-clean when finished.
This commit is contained in:
Emil
2026-06-22 00:06:30 +03:00
parent 9ce45cff4a
commit 4c1e3987ec
+11 -20
View File
@@ -1,12 +1,12 @@
use rodio::source::Source; use rodio::source::Source;
use rodio::{OutputStream, Sink}; use rodio::{OutputStream, OutputStreamHandle, Sink};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Cursor; use std::io::Cursor;
use std::time::Instant; use std::time::Instant;
pub struct AudioEngine { pub struct AudioEngine {
_stream: Option<OutputStream>, _stream: Option<OutputStream>,
sink: Option<Sink>, handle: Option<OutputStreamHandle>,
sounds: HashMap<&'static str, &'static [u8]>, sounds: HashMap<&'static str, &'static [u8]>,
last_played: HashMap<&'static str, Instant>, last_played: HashMap<&'static str, Instant>,
volume: f32, volume: f32,
@@ -22,13 +22,6 @@ impl AudioEngine {
return Self::disabled(); return Self::disabled();
} }
}; };
let sink = match Sink::try_new(&handle) {
Ok(s) => s,
Err(e) => {
eprintln!("Audio sink init failed: {}", e);
return Self::disabled();
}
};
let mut sounds = HashMap::new(); let mut sounds = HashMap::new();
sounds.insert( sounds.insert(
@@ -73,7 +66,7 @@ impl AudioEngine {
Self { Self {
_stream: Some(stream), _stream: Some(stream),
sink: Some(sink), handle: Some(handle),
sounds, sounds,
last_played: HashMap::new(), last_played: HashMap::new(),
volume: 0.5, volume: 0.5,
@@ -84,7 +77,7 @@ impl AudioEngine {
fn disabled() -> Self { fn disabled() -> Self {
Self { Self {
_stream: None, _stream: None,
sink: None, handle: None,
sounds: HashMap::new(), sounds: HashMap::new(),
last_played: HashMap::new(), last_played: HashMap::new(),
volume: 0.0, volume: 0.0,
@@ -112,13 +105,18 @@ impl AudioEngine {
Some(d) => *d, Some(d) => *d,
None => return, None => return,
}; };
let sink = match &self.sink { let handle = match &self.handle {
Some(s) => s, Some(h) => h,
None => return, None => return,
}; };
let sink = match Sink::try_new(handle) {
Ok(s) => s,
Err(_) => return,
};
if let Ok(decoder) = rodio::Decoder::new(Cursor::new(data.to_vec())) { if let Ok(decoder) = rodio::Decoder::new(Cursor::new(data.to_vec())) {
let source = decoder.amplify(self.volume).convert_samples::<f32>(); let source = decoder.amplify(self.volume).convert_samples::<f32>();
sink.append(source); sink.append(source);
sink.detach();
} }
} }
@@ -128,13 +126,6 @@ impl AudioEngine {
pub fn toggle(&mut self) { pub fn toggle(&mut self) {
self.enabled = !self.enabled; self.enabled = !self.enabled;
if let Some(sink) = &self.sink {
if !self.enabled {
sink.pause();
} else {
sink.play();
}
}
} }
pub fn is_enabled(&self) -> bool { pub fn is_enabled(&self) -> bool {