limnus_audio_sample/
lib.rs1use limnus_app::prelude::{App, Plugin};
6use limnus_asset_registry::AssetRegistry;
7use limnus_assets::Assets;
8use limnus_assets::prelude::{AssetName, RawWeakId};
9use limnus_assets_loader::{
10 AssetLoader, ConversionError, ResourceStorage, WrappedAssetLoaderRegistry,
11};
12use limnus_audio_mixer::StereoSample;
13use limnus_local_resource::LocalResourceStorage;
14use tracing::debug;
15
16#[must_use]
17pub fn load_wav(payload: &[u8]) -> StereoSample {
18 let mut reader = hound::WavReader::new(payload).expect("could not convert wav file");
19 let hound::WavSpec {
20 sample_rate: source_sample_rate,
21 sample_format,
22 bits_per_sample,
23 channels,
24 ..
25 } = reader.spec();
26 assert_eq!(channels, 2);
30
31 let samples_result: Result<Vec<f32>, _> = match sample_format {
33 hound::SampleFormat::Int => {
34 let max_value = 2_u32.pow(u32::from(bits_per_sample) - 1) - 1;
35 reader
36 .samples::<i32>()
37 .map(|sample| sample.map(|sample| sample as f32 / max_value as f32))
38 .collect()
39 }
40 hound::SampleFormat::Float => reader.samples::<f32>().collect(),
41 };
42 let mut samples = samples_result.unwrap();
43
44 let samples_stereo = oddio::frame_stereo(&mut samples);
45 let sound_frames = oddio::Frames::from_slice(source_sample_rate, samples_stereo);
46
47 StereoSample {
48 stereo_frames: sound_frames,
49 }
50}
51
52pub struct AudioSamplePlugin;
53
54impl Plugin for AudioSamplePlugin {
55 fn build(&self, app: &mut App) {
56 {
57 let registry = app.resource_mut::<WrappedAssetLoaderRegistry>();
58 let loader = StereoSampleConverter::new();
59
60 registry.value.lock().unwrap().register_loader(loader);
61 }
62 app.insert_resource(Assets::<StereoSample>::default());
63 }
64}
65
66#[derive(Default)]
67pub struct StereoSampleConverter;
68
69impl StereoSampleConverter {
70 #[must_use]
71 pub const fn new() -> Self {
72 Self {}
73 }
74}
75
76impl AssetLoader for StereoSampleConverter {
77 type AssetType = StereoSample;
78
79 fn convert_and_insert(
80 &self,
81 id: RawWeakId,
82 octets: &[u8],
83 resources: &mut ResourceStorage,
84 _local_resources: &mut LocalResourceStorage,
85 ) -> Result<(), ConversionError> {
86 let name: AssetName;
87 {
88 let asset_container = resources.fetch::<AssetRegistry>();
89 name = asset_container
90 .name_raw(id)
91 .expect("should know about this Id");
92 }
93
94 debug!("convert from wav {name}");
95 let stereo_sample = load_wav(octets);
96
97 debug!("converted wav {name}");
98 let stereo_sample_assets = resources.fetch_mut::<Assets<StereoSample>>();
99
100 stereo_sample_assets.set_raw(id, stereo_sample);
101
102 Ok(())
103 }
104}