Add ChangePart command and buffered audio sink

Introduce a `ChangePart` variant to `AudioCmd` and a `current_part`
state in
`handle_audio`.  The audio sink is now created via
`DeviceSinkBuilder::from_default_device` with a fixed buffer size.
`load_audio`
now accepts a reference to `SoundrackParts`, and the player
automatically
queues the correct part when the queue becomes empty.
This commit is contained in:
2026-04-09 01:08:50 +02:00
parent 56bef7c98e
commit 3e932e5638
+30 -20
View File
@@ -1,4 +1,6 @@
use rodio::{Decoder, DeviceSinkBuilder, MixerDeviceSink, Player, Source, source::Amplify};
use rodio::{
Decoder, DeviceSinkBuilder, MixerDeviceSink, Player, Source, cpal::BufferSize, source::Amplify,
};
use std::{fs::File, io::BufReader, sync::mpsc::Receiver};
#[derive(Debug)]
@@ -6,8 +8,10 @@ pub enum AudioCmd {
Mute,
VolumeUp,
VolumeDown,
ChangePart(SoundrackParts),
}
#[derive(Debug)]
pub enum SoundrackParts {
Calm,
Buildup,
@@ -15,7 +19,7 @@ pub enum SoundrackParts {
Outro,
}
fn load_audio(part: SoundrackParts) -> Amplify<Decoder<BufReader<File>>> {
fn load_audio(part: &SoundrackParts) -> Amplify<Decoder<BufReader<File>>> {
let file: File = match part {
SoundrackParts::Calm => File::open("soundtrack/default/test.ogg").expect("open audio file"),
SoundrackParts::Buildup => {
@@ -35,36 +39,33 @@ fn load_audio(part: SoundrackParts) -> Amplify<Decoder<BufReader<File>>> {
}
pub fn handle_audio(rx: Receiver<AudioCmd>, mute: bool) {
let mut handle: MixerDeviceSink =
DeviceSinkBuilder::open_default_sink().expect("open default audio stream");
let mut handle: MixerDeviceSink = DeviceSinkBuilder::from_default_device()
.expect("get default device")
.with_buffer_size(BufferSize::Fixed(4096))
.open_sink_or_fallback()
.expect("open device audio stream");
handle.log_on_drop(false);
let player: Player = Player::connect_new(&handle.mixer());
let mut volume: f32 = player.volume();
player.set_volume(if mute { 0.0 } else { volume });
if mute {
player.set_volume(0.0);
} else {
player.set_volume(volume);
}
// let preloaded_soundtrack_files: [File; 4] = [
// File::open("soundtrack/default/test.ogg").expect("open audio file"),
// File::open("soundtrack/default/test.ogg").expect("open audio file"),
// File::open("soundtrack/default/test.ogg").expect("open audio file"),
// File::open("soundtrack/default/test.ogg").expect("open audio file"),
// ];
player.append(load_audio(SoundrackParts::Calm));
let mut current_part: SoundrackParts = SoundrackParts::Calm;
player.append(load_audio(&current_part));
loop {
if player.empty() {
player.append(load_audio(SoundrackParts::Calm));
}
for cmd in rx.try_iter() {
match cmd {
AudioCmd::Mute => {
if player.volume() == 0.0 {
player.set_volume(volume);
} else {
player.set_volume(0.0);
}
player.set_volume(if player.volume() == 0.0 { volume } else { 0.0 });
}
AudioCmd::VolumeUp => {
volume = (volume + 0.1).min(1.0);
@@ -74,7 +75,16 @@ pub fn handle_audio(rx: Receiver<AudioCmd>, mute: bool) {
volume = (volume - 0.1).max(0.0);
player.set_volume(volume);
}
AudioCmd::ChangePart(part) => {
current_part = part;
player.append(load_audio(&current_part));
player.skip_one();
}
}
}
if player.empty() {
player.append(load_audio(&current_part));
}
}
}