Mercurial > touhou
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 |
| 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 } |
