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}