audio_engine/
lib.rs

1#![warn(missing_docs)]
2
3//! Audio Engine is a cross-platform crate for audio playback, build on top of cpal.
4//!
5//! ## Supported formats
6//! - ogg
7//! - wav
8//!
9//! ## Example
10//!
11//! ```no_run
12//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
13//! # let my_wav_sound = std::io::Cursor::new(vec![]);
14//! use audio_engine::{AudioEngine, WavDecoder};
15//! let audio_engine = AudioEngine::new()?;
16//! let mut sound = audio_engine.new_sound(WavDecoder::new(my_wav_sound)?)?;
17//! sound.play();
18//! # Ok(())
19//! # }
20//! ```
21
22use std::{
23    hash::Hash,
24    sync::{Arc, Mutex},
25};
26
27pub mod converter;
28mod sine;
29
30#[cfg(feature = "ogg")]
31mod ogg;
32#[cfg(feature = "wav")]
33mod wav;
34
35mod engine;
36pub use engine::AudioEngine;
37
38mod mixer;
39pub use mixer::Mixer;
40
41pub use sine::SineWave;
42
43#[cfg(feature = "ogg")]
44pub use ogg::OggDecoder;
45#[cfg(feature = "wav")]
46pub use wav::WavDecoder;
47
48/// The number of samples processed per second for a single channel of audio.
49#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
50pub struct SampleRate(pub u32);
51
52type SoundId = u64;
53
54/// Represents a sound in the AudioEngine.
55///
56/// If this is dropped, the sound will continue to play, but will be removed
57/// when it reachs its ends, even if it is set to loop.
58pub struct Sound<G: Eq + Hash + Send + 'static = ()> {
59    mixer: Arc<Mutex<Mixer<G>>>,
60    id: SoundId,
61}
62impl<G: Eq + Hash + Send + 'static> Sound<G> {
63    /// Starts or continue to play the sound.
64    ///
65    /// If the sound was paused or stop, it will start playing again. Otherwise,
66    /// does nothing.
67    pub fn play(&mut self) {
68        self.mixer.lock().unwrap().play(self.id);
69    }
70
71    /// Pause the sound.
72    ///
73    /// If the sound is playing, it will pause. If play is called, this sound
74    /// will continue from where it was before pause. If the sound is not
75    /// playing, does nothing.
76    pub fn pause(&mut self) {
77        self.mixer.lock().unwrap().pause(self.id);
78    }
79
80    /// Stop the sound.
81    ///
82    /// If the sound is playing, it will pause and reset the song. When play is
83    /// called, this sound will start from the beginning. Even if the sound is not
84    /// playing, it will reset the sound to the start.
85    pub fn stop(&mut self) {
86        self.mixer.lock().unwrap().stop(self.id);
87    }
88
89    /// Reset the sound to the start.
90    ///
91    /// The behaviour is the same being the sound playing or not.
92    pub fn reset(&mut self) {
93        self.mixer.lock().unwrap().reset(self.id);
94    }
95
96    /// Set the volume of the sound.
97    pub fn set_volume(&mut self, volume: f32) {
98        self.mixer.lock().unwrap().set_volume(self.id, volume);
99    }
100
101    /// Set if the sound will repeat ever time it reachs its end.
102    pub fn set_loop(&mut self, looping: bool) {
103        self.mixer.lock().unwrap().set_loop(self.id, looping);
104    }
105}
106impl<G: Eq + Hash + Send + 'static> Drop for Sound<G> {
107    fn drop(&mut self) {
108        self.mixer.lock().unwrap().mark_to_remove(self.id, true);
109    }
110}
111
112/// A source of sound samples.
113///
114/// Sound samples of each channel must be interleaved.
115pub trait SoundSource {
116    /// Return the number of channels.
117    fn channels(&self) -> u16;
118
119    /// Return the sample rate.
120    fn sample_rate(&self) -> u32;
121
122    /// Start the sound from the begining.
123    fn reset(&mut self);
124
125    /// Write the samples to `buffer`.
126    ///
127    /// Return how many samples was written. If it return a value less thand the length of
128    /// `buffer`, this indicate that the sound ended.
129    ///
130    /// The `buffer` length and the returned length should always be a multiple of
131    /// [`self.channels()`](SoundSource::channels).
132    fn write_samples(&mut self, buffer: &mut [i16]) -> usize;
133}
134impl<T: SoundSource + ?Sized> SoundSource for Box<T> {
135    fn channels(&self) -> u16 {
136        (**self).channels()
137    }
138
139    fn sample_rate(&self) -> u32 {
140        (**self).sample_rate()
141    }
142
143    fn reset(&mut self) {
144        (**self).reset()
145    }
146
147    fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
148        (**self).write_samples(buffer)
149    }
150}
151impl<T: SoundSource + ?Sized> SoundSource for Arc<Mutex<T>> {
152    fn channels(&self) -> u16 {
153        (*self).lock().unwrap().channels()
154    }
155
156    fn sample_rate(&self) -> u32 {
157        (*self).lock().unwrap().sample_rate()
158    }
159
160    fn reset(&mut self) {
161        (*self).lock().unwrap().reset()
162    }
163
164    fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
165        (*self).lock().unwrap().write_samples(buffer)
166    }
167}