aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src/audio/output.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mumd/src/audio/output.rs')
-rw-r--r--mumd/src/audio/output.rs26
1 files changed, 23 insertions, 3 deletions
diff --git a/mumd/src/audio/output.rs b/mumd/src/audio/output.rs
index cdb7b8e..b945710 100644
--- a/mumd/src/audio/output.rs
+++ b/mumd/src/audio/output.rs
@@ -1,3 +1,5 @@
+//! Receives audio packets from the networking and plays them.
+
use crate::audio::SAMPLE_RATE;
use crate::error::{AudioError, AudioStream};
use crate::network::VoiceStreamType;
@@ -16,12 +18,13 @@ use tokio::sync::watch;
type ClientStreamKey = (VoiceStreamType, u32);
+/// State for decoding audio received from another user.
pub struct ClientAudioData {
buf: Bounded<Vec<f32>>,
output_channels: opus::Channels,
- //we need two since a client can hypothetically send both mono
- //and stereo packets, and we can't switch a decoder on the fly
- //to reuse it
+ // We need both since a client can hypothetically send both mono
+ // and stereo packets, and we can't switch a decoder on the fly
+ // to reuse it.
mono_decoder: opus::Decoder,
stereo_decoder: opus::Decoder,
}
@@ -62,6 +65,7 @@ impl ClientAudioData {
}
}
+/// Collected state for client opus decoders and sound effects.
pub struct ClientStream {
buffer_clients: HashMap<ClientStreamKey, ClientAudioData>,
buffer_effects: VecDeque<f32>,
@@ -90,6 +94,7 @@ impl ClientStream {
)
}
+ /// Decodes a voice packet.
pub fn decode_packet(&mut self, client: ClientStreamKey, payload: VoicePacketPayload) {
match payload {
VoicePacketPayload::Opus(bytes, _eot) => {
@@ -101,12 +106,19 @@ impl ClientStream {
}
}
+ /// Extends the sound effect buffer queue with some received values.
pub fn add_sound_effect(&mut self, values: &[f32]) {
self.buffer_effects.extend(values.iter().copied());
}
}
+/// Adds two values in some saturating way.
+///
+/// Since we support [f32], [i16] and [u16] we need some way of adding two values
+/// without peaking above/below the edge values. This trait ensures that we can
+/// use all three primitive types as a generic parameter.
pub trait SaturatingAdd {
+ /// Adds two values in some saturating way. See trait documentation.
fn saturating_add(self, rhs: Self) -> Self;
}
@@ -140,14 +152,20 @@ pub trait AudioOutputDevice {
fn client_streams(&self) -> Arc<Mutex<ClientStream>>;
}
+/// The default audio output device, as determined by [cpal].
pub struct DefaultAudioOutputDevice {
config: StreamConfig,
stream: cpal::Stream,
+ /// The client stream per user ID. A separate stream is kept for UDP and TCP.
+ ///
+ /// Shared with [super::AudioOutput].
client_streams: Arc<Mutex<ClientStream>>,
+ /// Output volume configuration.
volume_sender: watch::Sender<f32>,
}
impl DefaultAudioOutputDevice {
+ /// Initializes the default audio output.
pub fn new(
output_volume: f32,
user_volumes: Arc<Mutex<HashMap<u32, (f32, bool)>>>,
@@ -247,6 +265,8 @@ impl AudioOutputDevice for DefaultAudioOutputDevice {
}
}
+/// Returns a function that fills a buffer with audio from client streams
+/// modified according to some audio configuration.
pub fn callback<T: Sample + AddAssign + SaturatingAdd + std::fmt::Display>(
user_bufs: Arc<Mutex<ClientStream>>,
output_volume_receiver: watch::Receiver<f32>,