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;