Mercurial > touhou
annotate python/src/audio.rs @ 796:d876ac2ccfe1 default tip
Pass audio only once to GameRunner
This prevents it being recreated every stage change, and playing music over the
previous stages’ music.
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Sun, 28 Jun 2026 14:27:03 +0200 |
| 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 |
|
796
d876ac2ccfe1
Pass audio only once to GameRunner
Link Mauve <linkmauve@linkmauve.fr>
parents:
783
diff
changeset
|
35 fn load_bgms(&mut self, bgms: [Option<(String, String)>; 4]) { |
|
d876ac2ccfe1
Pass audio only once to GameRunner
Link Mauve <linkmauve@linkmauve.fr>
parents:
783
diff
changeset
|
36 self.bgms = bgms; |
|
d876ac2ccfe1
Pass audio only once to GameRunner
Link Mauve <linkmauve@linkmauve.fr>
parents:
783
diff
changeset
|
37 } |
|
d876ac2ccfe1
Pass audio only once to GameRunner
Link Mauve <linkmauve@linkmauve.fr>
parents:
783
diff
changeset
|
38 |
|
783
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
39 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
|
40 let Some((_name, filename)) = &self.bgms[number] else { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
41 eprintln!("Unspecified bgm number {number}"); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
42 return; |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
43 }; |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
44 |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
45 // Load the loop points corresponding to this bgm. |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
46 let mut filename = PathBuf::from(filename); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
47 filename.set_extension("pos"); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
48 let loader = self.loader.borrow(py); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
49 let loop_points = loader |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
50 .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
|
51 .unwrap(); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
52 |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
53 // Then try to open the music file. |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
54 filename.set_extension("*"); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
55 let path = loader |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
56 .game_dir |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
57 .clone() |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
58 .and_then(|dir| Some(dir.join(&filename))) |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
59 .unwrap_or(filename); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
60 let mut music = None; |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
61 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
|
62 .unwrap() |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
63 .map(Result::unwrap) |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
64 .map(PathBuf::from) |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
65 { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
66 match StreamingSoundData::from_file(&path) { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
67 Ok(sound) => { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
68 music = Some(sound); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
69 break; |
|
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 Err(err) => { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
72 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
|
73 continue; |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
74 } |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
75 } |
|
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 let Some(music) = music else { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
78 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
|
79 return; |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
80 }; |
|
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 // Stop the previous playing one. |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
83 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
|
84 current_music.stop(Tween::default()); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
85 } |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
86 |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
87 // 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
|
88 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
|
89 // 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
|
90 current_music.set_loop_region( |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
91 (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
|
92 ); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
93 self.current_music = Some(current_music); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
94 } |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
95 |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
96 fn play(&mut self, py: Python, name: &str) { |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
97 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
|
98 let loader = self.loader.borrow(py); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
99 let bytes = loader.get_file_internal(name).unwrap(); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
100 let cursor = Cursor::new(bytes); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
101 StaticSoundData::from_cursor(cursor).unwrap() |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
102 }); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
103 self.manager.play(sound.clone()).unwrap(); |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
104 } |
|
ec1e06402a97
Replace SDL2_mixer with the kira crate
Link Mauve <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
105 } |
