ez_audi/samples_player/
exact_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, **DOES NOT transform the original sample into IntermediateSampleType which is much slower**.
10/// Go see SamplesPlayer for a more efficient samples player.
11pub struct ExactSamplesPlayer<T: Sample> {
12    original_samples: Samples<T>,
13    modifiers: Vec<Box<dyn ModifierTrait>>,
14    samples_with_modifiers: Option<Arc<Mutex<Samples<T>>>>,
15    stream: Option<cpal_abstraction::Stream>,
16}
17
18impl<T: Sample> ExactSamplesPlayer<T>
19where IntermediateSampleType: cpal::FromSample<T> {
20    /// Creates a new `SamplePlayer` directly from `Samples<T>`
21    pub fn new(samples: Samples<T>) -> ExactSamplesPlayer<T> {
22        Self {
23            original_samples: 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<T>>> {
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<T>) {
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().into_generic_representation_samples();
60        for modifier in &self.modifiers {
61            modified_samples = modifier.modify(modified_samples);
62        }
63
64        let t_samples = modified_samples.into_t_samples();
65        
66        self.change_samples_with_modifiers(t_samples);
67    }
68
69    fn set_stream(&mut self, stream: cpal_abstraction::Stream) {
70        self.apply_modifiers();
71
72        self.stream = Some(stream);
73    }
74}
75
76impl<T: Sample> SamplesPlayerTrait for ExactSamplesPlayer<T>
77where IntermediateSampleType: cpal::FromSample<T> {
78    fn metadata(&self) -> Box<dyn AudioMetadataTrait> {
79        Box::new(self.original_samples.metadata.clone())
80    }
81
82    fn add_modifier(&mut self, modifier: Box<dyn ModifierTrait>) {
83        self.modifiers.push(modifier);
84        
85        self.apply_modifiers();
86    }
87
88    fn clear_modifiers(&mut self) {
89        self.modifiers = Vec::new();
90
91        self.apply_modifiers();
92    }
93
94    fn start(&self) -> Error<()> {
95        let stream = match &self.stream {
96            Some(s) => s,
97            None => return Ok(()), // No stream to start
98        };
99
100        stream.start()
101    }
102
103    fn stop(&self) -> Error<()> {
104        let stream = match &self.stream {
105            Some(s) => s,
106            None => return Ok(()), // No stream to stop
107        };
108
109        stream.stop()
110    }
111
112    fn play_on_device(&mut self, device: Device) -> Error<()> {
113        // Makes sure that there is a Sample in self.samples_with_modifiers
114        self.apply_modifiers();
115
116        let samples_arc = self.samples_with_modifiers
117            .as_ref()
118            .expect("no samples with modifiers");
119        let samples_arc = Arc::clone(samples_arc);
120
121        let stream = device.create_stream(&self.original_samples.metadata,
122            samples_arc)?;
123
124        // Makes sure that the stream is started
125        stream.start()?;
126
127        self.set_stream(stream);
128
129        Ok(())
130    }
131}