awedio/
sound.rs

1use std::{
2    ops::{Deref, DerefMut},
3    time::Duration,
4};
5
6use crate::{
7    sounds::{
8        wrappers::{
9            AdjustableSpeed, AdjustableVolume, Controllable, Controller, FinishAfter, Pausable,
10            SetPaused, Stoppable,
11        },
12        MemorySound,
13    },
14    utils,
15};
16
17/// A provider of audio samples.
18///
19/// This is the foundational trait of this crate. A `Box<dyn Sound>` can be
20/// played on a [Manager][crate::manager::Manager]. Sounds can be wrapped to
21/// modify the inner sound, often by using helper functions of this trait
22/// (e.g. [pausable][Sound::pausable]).
23pub trait Sound: Send {
24    /// Returns the number of channels.
25    fn channel_count(&self) -> u16;
26
27    /// Returns the number of samples per second for each channel for this sound
28    /// (e.g. 48,000).
29    fn sample_rate(&self) -> u32;
30
31    /// Retrieve the next sample or notification if something has changed.
32    /// The first sample is for the first channel and the second is the for
33    /// second and so on until channel_count and then wraps back to the first
34    /// channel. If any NextSample variant besides `Sample` is returned then
35    /// the following `NextSample::Sample` is for the first channel. If a Sound
36    /// has returned `Paused` it is expected that the consumer will call
37    /// next_sample again in the future. If a Sound has returned `Finished` it
38    /// is not expected for the consumer to call next_sample again but if called
39    /// `Finished` will normally be returned again. After Finished has been
40    /// returned, channel_count() and sample_rate() may return different values
41    /// without MetadataChanged being returned.
42    ///
43    /// If an error is returned it is not specified what will happen if
44    /// next_sample is called again. Individual implementations can specify
45    /// which errors are recoverable if any. Most consumers will either pass the
46    /// error up or log the error and stop playing the sound (e.g. `SoundMixer`
47    /// and `SoundList`).
48    fn next_sample(&mut self) -> Result<NextSample, crate::Error>;
49
50    /// Called whenever a new batch of audio samples is requested by the
51    /// backend.
52    ///
53    /// This is a good place to put code that needs to run fairly frequently,
54    /// but not for every single audio sample.
55    fn on_start_of_batch(&mut self);
56
57    /// Returns the next sample for all channels.
58    ///
59    /// It is the callers responsibility to ensure this function is only called
60    /// at the start of a frame (i.e. the first channel is the next to be
61    /// returned from next_sample).
62    ///
63    /// If an Error, `Paused`, `Finished`, or `MetadataChanged` are encountered
64    /// while collecting samples, an Err(Ok(NextSample)) of that variant
65    /// will be returned and any previously collected samples are lost.
66    /// Err(Ok(NextSample::Sample)) will never be returned. If an error is
67    /// encountered Err(Err(error::Error)) is returned.
68    fn next_frame(&mut self) -> Result<Vec<i16>, Result<NextSample, crate::Error>> {
69        let mut samples = Vec::with_capacity(self.channel_count() as usize);
70        self.append_next_frame_to(&mut samples)?;
71        Ok(samples)
72    }
73
74    /// Same as `next_frame` but samples are appended into an existing Vec.
75    ///
76    /// Any existing data is left unmodified.
77    fn append_next_frame_to(
78        &mut self,
79        samples: &mut Vec<i16>,
80    ) -> Result<(), Result<NextSample, crate::Error>> {
81        for _ in 0..self.channel_count() {
82            let next = self.next_sample();
83            match next {
84                Ok(NextSample::Sample(s)) => samples.push(s),
85                Ok(NextSample::MetadataChanged)
86                | Ok(NextSample::Paused)
87                | Ok(NextSample::Finished)
88                | Err(_) => return Err(next),
89            }
90        }
91        Ok(())
92    }
93
94    /// Read the entire sound into memory. MemorySound can be cloned for
95    /// efficient reuse. See [MemorySound::from_sound].
96    fn into_memory_sound(self) -> Result<MemorySound, crate::Error>
97    where
98        Self: Sized,
99    {
100        MemorySound::from_sound(self)
101    }
102
103    /// Read the entire sound into memory and loop indefinitely.
104    ///
105    /// If you do not want to read the entire sound into memory see
106    /// [SoundsFromFn][crate::sounds::SoundsFromFn] as an alternative.
107    fn loop_from_memory(self) -> Result<MemorySound, crate::Error>
108    where
109        Self: Sized,
110    {
111        let mut to_return = MemorySound::from_sound(self)?;
112        to_return.set_looping(true);
113        Ok(to_return)
114    }
115
116    /// Allow this sound to be controlled after it has started playing with a
117    /// [`Controller`].
118    ///
119    /// What can be controlled depends on the Sound type (e.g. set_volume).
120    fn controllable(self) -> (Controllable<Self>, Controller<Self>)
121    where
122        Self: Sized,
123    {
124        Controllable::new(self)
125    }
126
127    /// Get notified via a [tokio::sync::oneshot::Receiver] when this sound
128    /// has Finished.
129    #[cfg(feature = "async")]
130    fn with_async_completion_notifier(
131        self,
132    ) -> (
133        crate::sounds::wrappers::AsyncCompletionNotifier<Self>,
134        tokio::sync::oneshot::Receiver<()>,
135    )
136    where
137        Self: Sized,
138    {
139        crate::sounds::wrappers::AsyncCompletionNotifier::new(self)
140    }
141
142    /// Get notified via a [std::sync::mpsc::Receiver] when this sound
143    /// has Finished.
144    fn with_completion_notifier(
145        self,
146    ) -> (
147        crate::sounds::wrappers::CompletionNotifier<Self>,
148        std::sync::mpsc::Receiver<()>,
149    )
150    where
151        Self: Sized,
152    {
153        crate::sounds::wrappers::CompletionNotifier::new(self)
154    }
155
156    /// Allow the volume of the sound to be adjustable with `set_volume`.
157    fn with_adjustable_volume(self) -> AdjustableVolume<Self>
158    where
159        Self: Sized,
160    {
161        AdjustableVolume::new(self)
162    }
163
164    /// Allow the volume of the sound to be adjustable with `set_volume` and set
165    /// the initial volume adjustment.
166    fn with_adjustable_volume_of(self, volume_adjustment: f32) -> AdjustableVolume<Self>
167    where
168        Self: Sized,
169    {
170        AdjustableVolume::new_with_volume(self, volume_adjustment)
171    }
172
173    /// Allow the speed of the sound to be adjustable with `set_speed`.
174    ///
175    /// This adjusts both speed and pitch.
176    fn with_adjustable_speed(self) -> AdjustableSpeed<Self>
177    where
178        Self: Sized,
179    {
180        AdjustableSpeed::new(self)
181    }
182
183    /// Allow the speed of the sound to be adjustable with `set_speed` and set
184    /// the initial speed adjustment.
185    ///
186    /// This adjusts both speed and pitch.
187    fn with_adjustable_speed_of(self, speed_adjustment: f32) -> AdjustableSpeed<Self>
188    where
189        Self: Sized,
190    {
191        AdjustableSpeed::new_with_speed(self, speed_adjustment)
192    }
193
194    /// Allow for the sound to be pausable with `set_paused`. Starts unpaused.
195    fn pausable(self) -> Pausable<Self>
196    where
197        Self: Sized,
198    {
199        Pausable::new(self)
200    }
201
202    /// Allow for the sound to be pausable with `set_paused`. Starts paused.
203    fn paused(self) -> Pausable<Self>
204    where
205        Self: Sized,
206    {
207        let mut to_return = Pausable::new(self);
208        to_return.set_paused(true);
209        to_return
210    }
211
212    /// Allow for the sound to be stoppable with `set_stopped`.
213    /// A stopped sound returns `Finished`.
214    fn stoppable(self) -> Stoppable<Self>
215    where
216        Self: Sized,
217    {
218        Stoppable::new(self)
219    }
220
221    /// Play the first `duration` of the sound, then finish even if samples
222    /// remain.
223    ///
224    /// See [FinishAfter].
225    fn finish_after(self, duration: Duration) -> FinishAfter<Self>
226    where
227        Self: Sized,
228    {
229        FinishAfter::new(self, duration)
230    }
231
232    /// Skip the next `duration` of samples.
233    ///
234    /// This is done by calling next_sample repeatedly.
235    ///
236    /// Returns true if all samples were successfully skipped, false if a Paused
237    /// or Finished were encountered first. MetadataChanged events are handled
238    /// correctly but are not returned.
239    fn skip(&mut self, duration: Duration) -> Result<bool, crate::Error> {
240        let mut current_channel_count = self.channel_count();
241        let mut current_sample_rate = self.sample_rate();
242        let mut num_samples_remaining =
243            utils::duration_to_num_samples(duration, current_channel_count, current_sample_rate);
244
245        while num_samples_remaining > 0 {
246            let next = self.next_sample()?;
247            match next {
248                NextSample::Sample(_) => {
249                    num_samples_remaining -= 1;
250                }
251                NextSample::MetadataChanged => {
252                    let new_channel_count = self.channel_count();
253                    let new_sample_rate = self.sample_rate();
254                    if new_channel_count != current_channel_count
255                        || new_sample_rate != current_sample_rate
256                    {
257                        num_samples_remaining = utils::convert_num_samples(
258                            num_samples_remaining,
259                            current_channel_count,
260                            current_sample_rate,
261                            new_channel_count,
262                            new_sample_rate,
263                        );
264                        current_channel_count = new_channel_count;
265                        current_sample_rate = new_sample_rate;
266                    }
267                }
268                NextSample::Paused => return Ok(false),
269                NextSample::Finished => return Ok(false),
270            }
271        }
272        Ok(true)
273    }
274}
275
276/// The result of [Sound::next_sample]
277#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
278pub enum NextSample {
279    /// A sample for one channel. Channels are interleaved. The first sample is
280    /// for the first channel and so forth and repeats (e.g. L-R-L-R-L-R).
281    Sample(i16),
282
283    /// The number of channels or the sample rate has changed. Continue to
284    /// retrieve samples afterward. The next sample will always be for the
285    /// first track regardless of what track was next
286    // before this value was returned.
287    MetadataChanged,
288
289    /// No more samples for now. More might come later. It is expected that the
290    /// Sound will not be pulled again during this batch of samples.
291    Paused,
292
293    /// All samples have been retrieved and no more will come.
294    Finished,
295}
296
297impl Sound for Box<dyn Sound> {
298    fn on_start_of_batch(&mut self) {
299        self.deref_mut().on_start_of_batch()
300    }
301
302    fn channel_count(&self) -> u16 {
303        self.deref().channel_count()
304    }
305
306    fn sample_rate(&self) -> u32 {
307        self.deref().sample_rate()
308    }
309
310    fn next_sample(&mut self) -> Result<NextSample, crate::Error> {
311        self.deref_mut().next_sample()
312    }
313}
314
315#[cfg(test)]
316#[path = "./tests/sound.rs"]
317mod tests;