annotate python/src/audio.rs @ 792:11bc22bad1bf default tip

python: Replace the image crate with png We weren’t using any of its features anyway, so the png crate is exactly what we need, without the many heavy dependencies of image. https://github.com/image-rs/image-png/pull/670 will eventually make it even faster to build.
author Link Mauve <linkmauve@linkmauve.fr>
date Sat, 17 Jan 2026 22:22:25 +0100
parents ec1e06402a97
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
783
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
1 use kira::sound::static_sound::StaticSoundData;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
2 use kira::sound::streaming::{StreamingSoundData, StreamingSoundHandle};
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
3 use kira::sound::FromFileError;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
4 use kira::{AudioManager, AudioManagerSettings, Tween};
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
5 use pyo3::prelude::*;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
6 use std::collections::HashMap;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
7 use std::io::Cursor;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
8 use std::path::PathBuf;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
9
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
10 #[pyclass(module = "libtouhou")]
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
11 pub struct Audio {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
12 loader: Py<super::Loader>,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
13 manager: AudioManager,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
14 cache: HashMap<String, StaticSoundData>,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
15 bgms: [Option<(String, String)>; 4],
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
16 current_music: Option<StreamingSoundHandle<FromFileError>>,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
17 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
18
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
19 #[pymethods]
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
20 impl Audio {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
21 #[new]
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
22 fn new(loader: Py<super::Loader>, bgms: [Option<(String, String)>; 4]) -> Audio {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
23 let manager =
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
24 AudioManager::<kira::DefaultBackend>::new(AudioManagerSettings::default()).unwrap();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
25 let cache = HashMap::new();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
26 Audio {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
27 loader,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
28 manager,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
29 cache,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
30 bgms,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
31 current_music: None,
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
32 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
33 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
34
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
35 fn play_bgm(&mut self, py: Python, number: usize) {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
36 let Some((_name, filename)) = &self.bgms[number] else {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
37 eprintln!("Unspecified bgm number {number}");
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
38 return;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
39 };
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
40
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
41 // Load the loop points corresponding to this bgm.
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
42 let mut filename = PathBuf::from(filename);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
43 filename.set_extension("pos");
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
44 let loader = self.loader.borrow(py);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
45 let loop_points = loader
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
46 .get_loop_points(filename.file_name().unwrap().to_str().unwrap())
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
47 .unwrap();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
48
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
49 // Then try to open the music file.
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
50 filename.set_extension("*");
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
51 let path = loader
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
52 .game_dir
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
53 .clone()
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
54 .and_then(|dir| Some(dir.join(&filename)))
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
55 .unwrap_or(filename);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
56 let mut music = None;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
57 for path in glob::glob(path.to_str().unwrap())
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
58 .unwrap()
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
59 .map(Result::unwrap)
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
60 .map(PathBuf::from)
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
61 {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
62 match StreamingSoundData::from_file(&path) {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
63 Ok(sound) => {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
64 music = Some(sound);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
65 break;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
66 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
67 Err(err) => {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
68 eprintln!("Error while opening {path:?} as a music file: {err:?}");
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
69 continue;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
70 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
71 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
72 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
73 let Some(music) = music else {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
74 eprintln!("Unable to find bgm, let’s keep the previous one playing…");
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
75 return;
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
76 };
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
77
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
78 // Stop the previous playing one.
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
79 if let Some(current_music) = &mut self.current_music {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
80 current_music.stop(Tween::default());
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
81 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
82
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
83 // And now we can start playing the new one!
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
84 let mut current_music = self.manager.play(music).unwrap();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
85 // TODO: Fetch the sample rate from the file, instead of hardcoding it.
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
86 current_music.set_loop_region(
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
87 (loop_points.start as f64 / 44100.0)..(loop_points.end as f64 / 44100.0),
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
88 );
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
89 self.current_music = Some(current_music);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
90 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
91
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
92 fn play(&mut self, py: Python, name: &str) {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
93 let sound = self.cache.entry(name.to_string()).or_insert_with(|| {
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
94 let loader = self.loader.borrow(py);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
95 let bytes = loader.get_file_internal(name).unwrap();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
96 let cursor = Cursor::new(bytes);
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
97 StaticSoundData::from_cursor(cursor).unwrap()
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
98 });
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
99 self.manager.play(sound.clone()).unwrap();
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
100 }
ec1e06402a97 Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff changeset
101 }