aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src/audio/input.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mumd/src/audio/input.rs')
-rw-r--r--mumd/src/audio/input.rs35
1 files changed, 31 insertions, 4 deletions
diff --git a/mumd/src/audio/input.rs b/mumd/src/audio/input.rs
index a1227e3..4dfc465 100644
--- a/mumd/src/audio/input.rs
+++ b/mumd/src/audio/input.rs
@@ -1,6 +1,8 @@
+//! Listens to the microphone and sends it to the networking.
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{InputCallbackInfo, Sample, SampleFormat, SampleRate, StreamConfig};
use log::*;
+use std::fmt::Debug;
use tokio::sync::watch;
use crate::audio::SAMPLE_RATE;
@@ -8,6 +10,7 @@ use crate::audio::transformers::{NoiseGate, Transformer};
use crate::error::{AudioError, AudioStream};
use crate::state::StatePhase;
+/// Generates a callback that receives [Sample]s and sends them as floats to a [futures_channel::mpsc::Sender].
pub fn callback<T: Sample>(
mut input_sender: futures_channel::mpsc::Sender<Vec<u8>>,
mut transformers: Vec<Box<dyn Transformer + Send + 'static>>,
@@ -29,8 +32,8 @@ pub fn callback<T: Sample>(
buffer.extend(data.by_ref().take(buffer_size - buffer.len()));
let encoded = transformers
.iter_mut()
- .try_fold(&mut buffer[..], |acc, e| e.transform(acc))
- .map(|buf| opus_encoder.encode_vec_float(&*buf, buffer_size).unwrap());
+ .try_fold((opus::Channels::Mono, &mut buffer[..]), |acc, e| e.transform(acc))
+ .map(|buf| opus_encoder.encode_vec_float(&*buf.1, buffer_size).unwrap());
if let Some(encoded) = encoded {
if let Err(e) = input_sender.try_send(encoded) {
@@ -43,11 +46,19 @@ pub fn callback<T: Sample>(
}
}
+/// Something that can listen to audio and send it somewhere.
+///
+/// One sample is assumed to be an encoded opus frame. See [opus::Encoder].
pub trait AudioInputDevice {
+ /// Starts the device.
fn play(&self) -> Result<(), AudioError>;
+ /// Stops the device.
fn pause(&self) -> Result<(), AudioError>;
+ /// Sets the input volume of the device.
fn set_volume(&self, volume: f32);
+ /// Returns a receiver to this device's values.
fn sample_receiver(&mut self) -> Option<futures_channel::mpsc::Receiver<Vec<u8>>>;
+ /// The amount of channels this device has.
fn num_channels(&self) -> usize;
}
@@ -59,6 +70,7 @@ pub struct DefaultAudioInputDevice {
}
impl DefaultAudioInputDevice {
+ /// Initializes the default audio input.
pub fn new(
input_volume: f32,
phase_watcher: watch::Receiver<StatePhase>,
@@ -160,20 +172,35 @@ impl AudioInputDevice for DefaultAudioInputDevice {
fn play(&self) -> Result<(), AudioError> {
self.stream
.play()
- .map_err(|e| AudioError::InputPlayError(e))
+ .map_err(AudioError::InputPlayError)
}
+
fn pause(&self) -> Result<(), AudioError> {
self.stream
.pause()
- .map_err(|e| AudioError::InputPauseError(e))
+ .map_err(AudioError::InputPauseError)
}
+
fn set_volume(&self, volume: f32) {
self.volume_sender.send(volume).unwrap();
}
+
fn sample_receiver(&mut self) -> Option<futures_channel::mpsc::Receiver<Vec<u8>>> {
self.sample_receiver.take()
}
+
fn num_channels(&self) -> usize {
self.channels as usize
}
}
+
+impl Debug for DefaultAudioInputDevice {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("DefaultAudioInputDevice")
+ .field("sample_receiver", &self.sample_receiver)
+ .field("channels", &self.channels)
+ .field("volume_sender", &self.volume_sender)
+ .field("stream", &"cpal::Stream")
+ .finish()
+ }
+}