1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#![warn(missing_docs)]

//! Audio Engine is a cross-platform crate for audio playback, build on top of cpal.
//!
//! ## Supported formats
//! - ogg
//! - wav
//!
//! ## Example
//!
//! ```no_run
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let my_wav_sound = std::io::Cursor::new(vec![]);
//! use audio_engine::{AudioEngine, WavDecoder};
//! let audio_engine = AudioEngine::new()?;
//! let mut sound = audio_engine.new_sound(WavDecoder::new(my_wav_sound)?)?;
//! sound.play();
//! # Ok(())
//! # }
//! ```

use std::{
    hash::Hash,
    sync::{Arc, Mutex},
};

pub mod converter;
mod ogg;
mod sine;
mod wav;

mod engine;
pub use engine::AudioEngine;

mod mixer;
pub use mixer::Mixer;

pub use ogg::OggDecoder;
pub use sine::SineWave;
pub use wav::WavDecoder;

/// The number of samples processed per second for a single channel of audio.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SampleRate(pub u32);

type SoundId = u64;

/// Represents a sound in the AudioEngine.
///
/// If this is dropped, the sound will continue to play, but will be removed
/// when it reachs its ends, even if it is set to loop.
pub struct Sound<G: Eq + Hash + Send + 'static = ()> {
    mixer: Arc<Mutex<Mixer<G>>>,
    id: SoundId,
}
impl<G: Eq + Hash + Send + 'static> Sound<G> {
    /// Starts or continue to play the sound.
    ///
    /// If the sound was paused or stop, it will start playing again. Otherwise,
    /// does nothing.
    pub fn play(&mut self) {
        self.mixer.lock().unwrap().play(self.id);
    }

    /// Pause the sound.
    ///
    /// If the sound is playing, it will pause. If play is called, this sound
    /// will continue from where it was before pause. If the sound is not
    /// playing, does nothing.
    pub fn pause(&mut self) {
        self.mixer.lock().unwrap().pause(self.id);
    }

    /// Stop the sound.
    ///
    /// If the sound is playing, it will pause and reset the song. When play is
    /// called, this sound will start from the beginning. Even if the sound is not
    /// playing, it will reset the sound to the start.
    pub fn stop(&mut self) {
        self.mixer.lock().unwrap().stop(self.id);
    }

    /// Reset the sound to the start.
    ///
    /// The behaviour is the same being the sound playing or not.
    pub fn reset(&mut self) {
        self.mixer.lock().unwrap().reset(self.id);
    }

    /// Set the volume of the sound.
    pub fn set_volume(&mut self, volume: f32) {
        self.mixer.lock().unwrap().set_volume(self.id, volume);
    }

    /// Set if the sound will repeat ever time it reachs its end.
    pub fn set_loop(&mut self, looping: bool) {
        self.mixer.lock().unwrap().set_loop(self.id, looping);
    }
}
impl<G: Eq + Hash + Send + 'static> Drop for Sound<G> {
    fn drop(&mut self) {
        self.mixer.lock().unwrap().mark_to_remove(self.id, true);
    }
}

/// A source of sound samples.
///
/// Sound samples of each channel must be interleaved.
pub trait SoundSource {
    /// Return the number of channels.
    fn channels(&self) -> u16;

    /// Return the sample rate.
    fn sample_rate(&self) -> u32;

    /// Start the sound from the begining.
    fn reset(&mut self);

    /// Write the samples to `buffer`.
    ///
    /// Return how many samples was written. If it return a value less thand the length of
    /// `buffer`, this indicate that the sound ended.
    ///
    /// The `buffer` length and the returned length should always be a multiple of
    /// [`self.channels()`](SoundSource::channels).
    fn write_samples(&mut self, buffer: &mut [i16]) -> usize;
}
impl<T: SoundSource + ?Sized> SoundSource for Box<T> {
    fn channels(&self) -> u16 {
        (**self).channels()
    }

    fn sample_rate(&self) -> u32 {
        (**self).sample_rate()
    }

    fn reset(&mut self) {
        (**self).reset()
    }

    fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
        (**self).write_samples(buffer)
    }
}
impl<T: SoundSource + ?Sized> SoundSource for Arc<Mutex<T>> {
    fn channels(&self) -> u16 {
        (*self).lock().unwrap().channels()
    }

    fn sample_rate(&self) -> u32 {
        (*self).lock().unwrap().sample_rate()
    }

    fn reset(&mut self) {
        (*self).lock().unwrap().reset()
    }

    fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
        (*self).lock().unwrap().write_samples(buffer)
    }
}