audio playback kinda works

This commit is contained in:
2024-11-12 20:05:44 -07:00
parent b2ee911c66
commit bcd73ae83f
+42 -30
View File
@@ -1,13 +1,11 @@
use crate::app::Command; use crate::app::Command;
use color_eyre::eyre::{eyre, Error}; use color_eyre::eyre::{eyre, Error};
use cpal::traits::{DeviceTrait, HostTrait}; use cpal::traits::{DeviceTrait, HostTrait};
use crossbeam_queue::ArrayQueue;
use dioxus::hooks::{UnboundedReceiver, UnboundedSender}; use dioxus::hooks::{UnboundedReceiver, UnboundedSender};
use futures::io::{AsyncRead, AsyncWrite}; use futures::io::{AsyncRead, AsyncWrite};
use mumble_protocol::control::{ClientControlCodec, ControlPacket}; use mumble_protocol::control::{ClientControlCodec, ControlPacket};
use mumble_protocol::Serverbound; use mumble_protocol::Serverbound;
use mumble_web2_common::GuiConfig; use mumble_web2_common::GuiConfig;
use std::collections::VecDeque;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::sync::Mutex; use std::sync::Mutex;
use std::{fmt, io, sync::Arc}; use std::{fmt, io, sync::Arc};
@@ -35,7 +33,7 @@ pub struct AudioSystem {
input: cpal::Device, input: cpal::Device,
} }
const BUF_LEN: usize = 480; // 20 ms type Buffer = Arc<Mutex<dasp_ring_buffer::Bounded<Vec<i16>>>>;
impl AudioSystem { impl AudioSystem {
pub fn new() -> Result<Self, Error> { pub fn new() -> Result<Self, Error> {
@@ -58,19 +56,35 @@ impl AudioSystem {
} }
pub fn create_player(&mut self) -> Result<AudioPlayer, Error> { pub fn create_player(&mut self) -> Result<AudioPlayer, Error> {
let queue = Arc::new(ArrayQueue::<[i16; BUF_LEN]>::new(10)); let buffer = Arc::new(Mutex::new(dasp_ring_buffer::Bounded::from_raw_parts(
0,
0,
vec![
0;
2400 // 50ms of buffer
],
)));
let decoder = opus::Decoder::new(48_000, opus::Channels::Mono)?; let decoder = opus::Decoder::new(48_000, opus::Channels::Mono)?;
let stream = { let stream = {
let queue = queue.clone(); let buffer = buffer.clone();
self.output.build_output_stream( self.output.build_output_stream(
&cpal::StreamConfig { &cpal::StreamConfig {
channels: 1, channels: 1,
sample_rate: cpal::SampleRate(48_000), sample_rate: cpal::SampleRate(48_000),
buffer_size: cpal::BufferSize::Fixed(BUF_LEN as u32), // 20ms playback delay buffer_size: cpal::BufferSize::Fixed(480), // 10ms playback delay
}, },
move |out, info| match queue.pop() { move |frame, info| {
Some(buf) => out.copy_from_slice(&buf[..]), let mut buffer = buffer.lock().unwrap();
None => out.fill(0), for x in frame.iter_mut() {
match buffer.pop() {
Some(y) => {
*x = y;
}
None => {
*x = 0;
}
}
}
}, },
move |err| error!("could not create output stream {err:?}"), move |err| error!("could not create output stream {err:?}"),
None, None,
@@ -79,9 +93,8 @@ impl AudioSystem {
Ok(AudioPlayer { Ok(AudioPlayer {
decoder, decoder,
stream, stream,
queue, buffer,
tmp: vec![0; 2400], tmp: vec![0; 2400],
pos: 0,
}) })
} }
} }
@@ -89,32 +102,31 @@ impl AudioSystem {
pub struct AudioPlayer { pub struct AudioPlayer {
decoder: opus::Decoder, decoder: opus::Decoder,
stream: cpal::Stream, stream: cpal::Stream,
queue: Arc<ArrayQueue<[i16; BUF_LEN]>>, buffer: Buffer,
tmp: Vec<i16>, tmp: Vec<i16>,
pos: usize,
} }
impl AudioPlayer { impl AudioPlayer {
pub fn play_opus(&mut self, payload: &[u8]) { pub fn play_opus(&mut self, payload: &[u8]) {
match self let len = loop {
.decoder match self.decoder.decode(payload, &mut self.tmp, false) {
.decode(payload, &mut self.tmp[self.pos..], false) Ok(l) => break l,
{ Err(e) => {
Ok(l) => { error!("opus decode error {e:?}");
self.pos += l; return;
} }
Err(e) => {
error!("opus decode error {e:?}");
} }
}; };
while self.pos >= BUF_LEN {
let mut chunk = [0; BUF_LEN]; let mut buffer = self.buffer.lock().unwrap();
chunk.copy_from_slice(&self.tmp[..BUF_LEN]); let mut overrun = 0;
dbg!(&chunk); for x in &self.tmp[..len] {
let _ = self.queue.push(chunk); if let Some(_) = buffer.push(*x) {
let i = std::cell::Cell::new(0usize); overrun += 1;
self.tmp.retain(|_| i.replace(i.get() + 1) >= BUF_LEN); }
self.pos -= BUF_LEN; }
if overrun > 0 {
warn!("playback overrun by {overrun} samples");
} }
} }
} }