diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2020-10-21 03:37:22 +0200 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2020-10-21 03:37:22 +0200 |
| commit | c9846394ac6cddd82442baadcabad653a28fed66 (patch) | |
| tree | b92afa32fa1e56f5542d921c8f9f1f3befa06648 /mumd/src/audio/input.rs | |
| parent | 1c18f57afe3eae3d61ad44c899d57332e0f71e0c (diff) | |
| download | mum-c9846394ac6cddd82442baadcabad653a28fed66.tar.gz | |
refactor audio into input.rs and output.rs
Diffstat (limited to 'mumd/src/audio/input.rs')
| -rw-r--r-- | mumd/src/audio/input.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/mumd/src/audio/input.rs b/mumd/src/audio/input.rs new file mode 100644 index 0000000..4e95360 --- /dev/null +++ b/mumd/src/audio/input.rs @@ -0,0 +1,52 @@ +use bytes::Bytes; +use cpal::{InputCallbackInfo, Sample}; +use mumble_protocol::voice::VoicePacketPayload; +use std::collections::VecDeque; +use std::sync::{Arc, Mutex}; +use tokio::sync::{mpsc, watch}; + +pub fn callback<T: Sample>( + mut opus_encoder: opus::Encoder, + mut input_sender: mpsc::Sender<VoicePacketPayload>, + sample_rate: u32, + input_volume_receiver: watch::Receiver<f32>, + opus_frame_size_blocks: u32, // blocks of 2.5ms +) -> impl FnMut(&[T], &InputCallbackInfo) + Send + 'static { + if !(opus_frame_size_blocks == 1 + || opus_frame_size_blocks == 2 + || opus_frame_size_blocks == 4 + || opus_frame_size_blocks == 8) + { + panic!( + "Unsupported amount of opus frame blocks {}", + opus_frame_size_blocks + ); + } + let opus_frame_size = opus_frame_size_blocks * sample_rate / 400; + + let buf = Arc::new(Mutex::new(VecDeque::new())); + move |data: &[T], _info: &InputCallbackInfo| { + let mut buf = buf.lock().unwrap(); + let input_volume = *input_volume_receiver.borrow(); + let out: Vec<f32> = data.iter().map(|e| e.to_f32()) + .map(|e| e * input_volume) + .collect(); + buf.extend(out); + while buf.len() >= opus_frame_size as usize { + let tail = buf.split_off(opus_frame_size as usize); + let mut opus_buf: Vec<u8> = vec![0; opus_frame_size as usize]; + let result = opus_encoder + .encode_float(&Vec::from(buf.clone()), &mut opus_buf) + .unwrap(); + opus_buf.truncate(result); + let bytes = Bytes::copy_from_slice(&opus_buf); + match input_sender.try_send(VoicePacketPayload::Opus(bytes, false)) { + Ok(_) => {} + Err(_e) => { + //warn!("Error sending audio packet: {:?}", e); + } + } + *buf = tail; + } + } +} |
