aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src/audio/input.rs
diff options
context:
space:
mode:
authorEskil Queseth <eskilq@kth.se>2021-06-12 02:30:01 +0200
committerEskil Queseth <eskilq@kth.se>2021-06-12 02:30:01 +0200
commitbc65445af44a335a0586a393c792614330258249 (patch)
treefd0ba08e7a1748076f04ce3d5678b960c5aaa4a7 /mumd/src/audio/input.rs
parentdcd70175a98c83a3334d7980e5196bc866e04efb (diff)
downloadmum-bc65445af44a335a0586a393c792614330258249.tar.gz
simplify audio output infrastructure
Diffstat (limited to 'mumd/src/audio/input.rs')
-rw-r--r--mumd/src/audio/input.rs79
1 files changed, 67 insertions, 12 deletions
diff --git a/mumd/src/audio/input.rs b/mumd/src/audio/input.rs
index e45ff27..162dd2c 100644
--- a/mumd/src/audio/input.rs
+++ b/mumd/src/audio/input.rs
@@ -8,20 +8,49 @@ use crate::error::{AudioError, AudioStream};
use crate::state::StatePhase;
pub fn callback<T: Sample>(
- mut input_sender: futures_channel::mpsc::Sender<f32>,
+ mut input_sender: futures_channel::mpsc::Sender<Vec<u8>>,
+ transformers: Vec<Box<dyn Fn(&mut [f32]) -> Option<&mut [f32]> + Send + 'static>>,
+ frame_size: u32,
+ sample_rate: u32,
+ channels: u16,
input_volume_receiver: watch::Receiver<f32>,
phase_watcher: watch::Receiver<StatePhase>,
) -> impl FnMut(&[T], &InputCallbackInfo) + Send + 'static {
+ let buffer_size = (sample_rate * frame_size / 400) as usize;
+ let mut opus_encoder = opus::Encoder::new(
+ sample_rate,
+ match channels {
+ 1 => opus::Channels::Mono,
+ 2 => opus::Channels::Stereo,
+ _ => unimplemented!("Only 1 or 2 channels supported, got {}", channels),
+ },
+ opus::Application::Voip,
+ )
+ .unwrap();
+ let mut buffer = Vec::with_capacity(buffer_size);
+
move |data: &[T], _info: &InputCallbackInfo| {
if !matches!(&*phase_watcher.borrow(), StatePhase::Connected(_)) {
return;
}
let input_volume = *input_volume_receiver.borrow();
- for sample in data.iter().map(|e| e.to_f32()).map(|e| e * input_volume) {
- if let Err(_e) = input_sender.try_send(sample) {
- warn!("Error sending audio: {}", _e);
+ let mut data = data.iter().map(|e| e.to_f32()).map(|e| e * input_volume);
+
+ while buffer.len() + data.len() > buffer_size {
+ buffer.extend(data.by_ref().take(buffer_size - buffer.len()));
+ let encoded = transformers
+ .iter()
+ .try_fold(&mut buffer[..], |acc, e| e(acc))
+ .map(|buf| opus_encoder.encode_vec_float(&*buf, buffer_size).unwrap());
+
+ if let Some(encoded) = encoded {
+ if let Err(e) = input_sender.try_send(encoded) {
+ warn!("Error sending audio: {}", e);
+ }
}
+ buffer.clear();
}
+ buffer.extend(data);
}
}
@@ -29,13 +58,13 @@ pub trait AudioInputDevice {
fn play(&self) -> Result<(), AudioError>;
fn pause(&self) -> Result<(), AudioError>;
fn set_volume(&self, volume: f32);
- fn sample_receiver(&mut self) -> futures_channel::mpsc::Receiver<f32>;
+ fn sample_receiver(&mut self) -> Option<futures_channel::mpsc::Receiver<Vec<u8>>>;
fn num_channels(&self) -> usize;
}
pub struct DefaultAudioInputDevice {
stream: cpal::Stream,
- sample_receiver: Option<futures_channel::mpsc::Receiver<f32>>,
+ sample_receiver: Option<futures_channel::mpsc::Receiver<Vec<u8>>>,
volume_sender: watch::Sender<f32>,
channels: u16,
}
@@ -44,6 +73,7 @@ impl DefaultAudioInputDevice {
pub fn new(
input_volume: f32,
phase_watcher: watch::Receiver<StatePhase>,
+ frame_size: u32,
) -> Result<Self, AudioError> {
let sample_rate = SampleRate(SAMPLE_RATE);
@@ -73,20 +103,46 @@ impl DefaultAudioInputDevice {
let (volume_sender, input_volume_receiver) = watch::channel::<f32>(input_volume);
+ let transformers = vec![];
+
let input_stream = match input_supported_sample_format {
SampleFormat::F32 => input_device.build_input_stream(
&input_config,
- callback::<f32>(sample_sender, input_volume_receiver, phase_watcher),
+ callback::<f32>(
+ sample_sender,
+ transformers,
+ frame_size,
+ SAMPLE_RATE,
+ input_config.channels,
+ input_volume_receiver,
+ phase_watcher
+ ),
err_fn,
),
SampleFormat::I16 => input_device.build_input_stream(
&input_config,
- callback::<i16>(sample_sender, input_volume_receiver, phase_watcher),
+ callback::<i16>(
+ sample_sender,
+ transformers,
+ frame_size,
+ SAMPLE_RATE,
+ input_config.channels,
+ input_volume_receiver,
+ phase_watcher
+ ),
err_fn,
),
SampleFormat::U16 => input_device.build_input_stream(
&input_config,
- callback::<u16>(sample_sender, input_volume_receiver, phase_watcher),
+ callback::<u16>(
+ sample_sender,
+ transformers,
+ frame_size,
+ SAMPLE_RATE,
+ input_config.channels,
+ input_volume_receiver,
+ phase_watcher
+ ),
err_fn,
),
}
@@ -116,9 +172,8 @@ impl AudioInputDevice for DefaultAudioInputDevice {
fn set_volume(&self, volume: f32) {
self.volume_sender.send(volume).unwrap();
}
- fn sample_receiver(&mut self) -> futures_channel::mpsc::Receiver<f32> {
- let ret = self.sample_receiver.take();
- ret.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