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:
+11
-20
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user