1use bevy::transform::components::Transform;
2use kira::{Decibels, Easing, Mapping, Tween, Value, effect::{filter::FilterBuilder}, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
3
4use crate::{FelixAudioComponent, source::{AudioSource, stream_source::sound_data::StreamAudioSourceSoundData}};
5
6mod sound_data;
7
8pub struct StreamAudioSource{
9 saturate_cb: Option<Box<dyn FnMut(usize) -> Vec<f32> + 'static + Sync + Send>>,
10 sample_rate: usize,
11
12 send_track: Option<SendTrackHandle>,
13 spatial_track: Option<SpatialTrackHandle>
14}
15
16impl StreamAudioSource{
17 pub fn new<T>( sample_rate: usize, saturate: T ) -> Self
18 where
19 T: FnMut(usize) -> Vec<f32> + 'static + Sync + Send
20 {
21 Self {
22 saturate_cb: Some(Box::new(saturate)),
23 sample_rate,
24
25 send_track: None,
26 spatial_track: None
27 }
28 }
29}
30
31impl AudioSource for StreamAudioSource{
32 fn init( &mut self, audio_system: &mut FelixAudioComponent ) {
33 let sound_data = StreamAudioSourceSoundData::new(self.sample_rate.clone(), self.saturate_cb.take().unwrap());
34 let send_track = audio_system.manager.add_send_track(SendTrackBuilder::new()).unwrap();
35
36 let mut spatial_track = audio_system.manager.add_spatial_sub_track(
37 &audio_system.main_listener,
38 [
39 0.0,
40 0.0,
41 0.0
42 ],
43 SpatialTrackBuilder::new()
44 .with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
45 input_range: ( 0.0, 20.0 ),
46 output_range: ( 18000.0, 2000.0 ),
47 easing: Easing::Linear
48 })))
49 .with_send(&send_track, Value::FromListenerDistance(Mapping {
50 input_range: ( 0.0, 1.0 ),
51 output_range: ( Decibels(12.0), Decibels(-100.0) ),
52 easing: Easing::Linear
53 }))
54 ).unwrap();
55
56 spatial_track.play(sound_data).unwrap();
57
58 self.send_track = Some(send_track);
59 self.spatial_track = Some(spatial_track);
60 }
61
62 fn needs_init( &self ) -> bool {
63 self.spatial_track.is_none()
64 }
65
66 fn update( &mut self, transform: &Transform ) {
67 let track = self.spatial_track.as_mut().unwrap();
68 track.set_position(transform.translation, Tween::default());
69 }
70}