ez_audi/samples_player/
samples_player.rs

1use std::sync::{Mutex, MutexGuard, Arc};
2
3use crate::{Device, traits::AudioMetadataTrait, cpal_abstraction, Error, modifiers::ModifierTrait};
4
5use cpal_abstraction::{Sample, Samples, SamplesTrait, IntermediateSampleType};
6
7use super::SamplesPlayerTrait;
8
9/// Manages the applying of modifiers and the sending of samples to audio streams, **transforms the original sample into IntermediateSampleType which is much more efficient**.
10/// Go see ExactSamplesPlayer to send the exact sample type of the original sample to the audio streams.
11pub struct SamplesPlayer {
12    original_samples: Samples<IntermediateSampleType>,
13    modifiers: Vec<Box<dyn ModifierTrait>>,
14    samples_with_modifiers: Option<Arc<Mutex<Samples<IntermediateSampleType>>>>,
15    stream: Option<cpal_abstraction::Stream>,
16}
17
18impl SamplesPlayer {
19    /// Creates a new `SamplePlayer` directly from `Samples<T>`
20    pub fn new<T: Sample>(samples: Samples<T>) -> SamplesPlayer
21    where IntermediateSampleType: cpal::FromSample<T> {
22        Self {
23            original_samples: samples.into_generic_representation_samples(),
24            modifiers: Vec::new(),
25            samples_with_modifiers: None,
26            stream: None,
27        }
28    }
29
30    fn aquire_samples_with_modifiers_mutex_guard(&self) -> Option<MutexGuard<Samples<IntermediateSampleType>>> {
31        let modified_samples_mutex = match &self.samples_with_modifiers {
32            Some(m) => m,
33            None => return None,
34        };
35
36        let mutex_lock = modified_samples_mutex.lock();
37        match mutex_lock {
38            Ok(l) => Some(l),
39            // TODO: Better error handling on that // Kinda? the Option enum signifies that
40            Err(_) => None,
41        }
42    }
43
44    fn change_samples_with_modifiers(&mut self, samples: Samples<IntermediateSampleType>) {
45        let mutex_guard_option = self.aquire_samples_with_modifiers_mutex_guard();
46
47        if let Some(mut guard) = mutex_guard_option {
48            *guard = samples;
49        } else {
50            // Creates a Arc if there is none yet
51            drop(mutex_guard_option);
52            self.samples_with_modifiers = Some(Arc::new(Mutex::new(samples)))
53        }
54    }
55
56    /// Applies all the modifiers
57    fn apply_modifiers(&mut self) {
58        // Most of the time seems to be spent moving samples, cloning and transfering from one type to another
59        let mut modified_samples = self.original_samples.clone();
60        for modifier in &self.modifiers {
61            modified_samples = modifier.modify(modified_samples);
62        }
63
64        self.change_samples_with_modifiers(modified_samples);
65    }
66
67    fn set_stream(&mut self, stream: cpal_abstraction::Stream) {
68        self.apply_modifiers();
69
70        self.stream = Some(stream);
71    }
72}
73
74impl SamplesPlayerTrait for SamplesPlayer {
75    fn metadata(&self) -> Box<dyn AudioMetadataTrait> {
76        Box::new(self.original_samples.metadata.clone())
77    }
78
79    fn add_modifier(&mut self, modifier: Box<dyn ModifierTrait>) {
80        self.modifiers.push(modifier);
81        
82        self.apply_modifiers();
83    }
84
85    fn clear_modifiers(&mut self) {
86        self.modifiers = Vec::new();
87
88        self.apply_modifiers();
89    }
90
91    fn start(&self) -> Error<()> {
92        let stream = match &self.stream {
93            Some(s) => s,
94            None => return Ok(()), // No stream to start
95        };
96
97        stream.start()
98    }
99
100    fn stop(&self) -> Error<()> {
101        let stream = match &self.stream {
102            Some(s) => s,
103            None => return Ok(()), // No stream to stop
104        };
105
106        stream.stop()
107    }
108
109    fn play_on_device(&mut self, device: Device) -> Error<()> {
110        // Makes sure that there is a Sample in self.samples_with_modifiers
111        self.apply_modifiers();
112
113        let samples_arc = self.samples_with_modifiers
114            .as_ref()
115            .expect("no samples with modifiers");
116        let samples_arc = Arc::clone(samples_arc);
117
118        let stream = device.create_stream(&self.original_samples.metadata,
119            samples_arc)?;
120
121        // Makes sure that the stream is started
122        stream.start()?;
123
124        self.set_stream(stream);
125
126        Ok(())
127    }
128}