diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-16 15:29:57 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-16 15:29:57 +0100 |
commit | a11245c39d1551dc1e209c950d84c63931b604a5 (patch) | |
tree | 5f49e8205659881221e8e495b1d9f9ae9477e9bc /client | |
parent | 44220f3ff1015c056730c8ee4c95cb55a0759abc (diff) | |
download | weareserver-a11245c39d1551dc1e209c950d84c63931b604a5.tar weareserver-a11245c39d1551dc1e209c950d84c63931b604a5.tar.bz2 weareserver-a11245c39d1551dc1e209c950d84c63931b604a5.tar.zst |
fix audio ringbuf and improve vad
Diffstat (limited to 'client')
-rw-r--r-- | client/src/audio.rs | 32 | ||||
-rw-r--r-- | client/src/state.rs | 23 |
2 files changed, 36 insertions, 19 deletions
diff --git a/client/src/audio.rs b/client/src/audio.rs index f93466d..d90898a 100644 --- a/client/src/audio.rs +++ b/client/src/audio.rs @@ -56,7 +56,7 @@ impl Audio { inconf.buffer_size = cpal::BufferSize::Fixed(480); let mut outconf = outdev.default_input_config()?.config(); - outconf.channels = 1; + outconf.channels = 2; outconf.sample_rate = cpal::SampleRate(48_000); outconf.buffer_size = cpal::BufferSize::Fixed(480); @@ -101,6 +101,7 @@ impl Audio { } } +#[derive(Debug)] pub struct APlayPacket { pos: Vec3, channel: u128, @@ -156,10 +157,11 @@ impl AEncoder { let (tx, end_tx) = self.trigger.update(energy); if tx { let size = self.encoder.encode_float(&denoise, &mut out)?; + debug!("encoded size={size}"); let _ = self.sender.try_send(out[..size].to_vec()); } if end_tx { - // TODO send end frame + let _ = self.sender.try_send(vec![]); } } Ok(()) @@ -168,14 +170,14 @@ impl AEncoder { impl VadTrigger { pub fn update(&mut self, energy: f32) -> (bool, bool) { - debug!("E={energy:.02}"); let now = Instant::now(); - if energy > 1. { + let thres = if self.transmitting { 0.1 } else { 1. }; + if energy > thres { self.last_sig = now; } let last_sig_elapsed = (now - self.last_sig).as_secs_f32(); let prev_transmitting = self.transmitting; - self.transmitting = last_sig_elapsed < 0.5; + self.transmitting = last_sig_elapsed < 0.2; match (prev_transmitting, self.transmitting) { (false, true) => info!("start transmit"), @@ -188,6 +190,8 @@ impl VadTrigger { } const BUFFER_SIZE: usize = 48_000; +const JITTER_COMP: usize = 48_00 * 2; + pub struct ADecoder { decoder: Decoder, receiver: Receiver<APlayPacket>, @@ -210,8 +214,12 @@ impl ADecoder { )) } pub fn data(&mut self, samples: &mut [f32]) -> Result<()> { - while self.buffer.len() < samples.len() { - if let Ok(p) = self.receiver.try_recv() { + for p in self.receiver.try_iter() { + if p.data.is_empty() { + if self.channels.remove(&p.channel).is_some() { + info!("channel {} ended", p.channel % 1_000_000) + } + } else { let mut output = [0f32; AE_FRAME_SIZE]; let size = self.decoder.decode_float( Some(p.data.as_slice()), @@ -219,17 +227,19 @@ impl ADecoder { false, )?; - let channel_cursor = self.channels.entry(p.channel).or_insert(self.playback); + let channel_cursor = self.channels.entry(p.channel).or_insert_with(|| { + info!("channel {} started", p.channel % 1_000_000); + (self.playback + JITTER_COMP) % BUFFER_SIZE + }); let free_space = *channel_cursor - self.playback; for i in 0..size.min(free_space) { // TODO positional audio let _ = p.pos; - self.buffer[*channel_cursor] = [output[i], output[i]]; + self.buffer[*channel_cursor][0] += output[i]; + self.buffer[*channel_cursor][1] += output[i]; *channel_cursor += 1; *channel_cursor %= BUFFER_SIZE } - } else { - break; } } for x in samples.array_chunks_mut::<2>() { diff --git a/client/src/state.rs b/client/src/state.rs index e59691a..560c8bd 100644 --- a/client/src/state.rs +++ b/client/src/state.rs @@ -41,6 +41,7 @@ pub struct State<'a> { pub prefab_index_res_loaded: Option<Resource<PrefabIndex>>, pub prefab_index_res: Option<Resource<PrefabIndex>>, pub avatar_ob: Option<Object>, + pub last_position_tx: Instant, } pub struct InputState { @@ -73,6 +74,7 @@ impl<'a> State<'a> { prefab_index_res_loaded: None, avatar_ob: None, prefab_index: PrefabIndex::default().into(), + last_position_tx: Instant::now(), }) } pub fn draw(&mut self) { @@ -146,9 +148,11 @@ impl<'a> State<'a> { match &p { Packet::PrefabIndex(res) => self.prefab_index_res = Some(res.to_owned()), Packet::Sound(ob, data) => { - if let Some(obdata) = self.tree.objects.get(ob) { - self.audio - .incoming_packet(ob.0, obdata.pos.into(), data.0.clone()) + if Some(ob) != self.avatar_ob.as_ref() { + if let Some(obdata) = self.tree.objects.get(ob) { + self.audio + .incoming_packet(ob.0, obdata.pos.into(), data.0.clone()) + } } } _ => (), @@ -169,11 +173,14 @@ impl<'a> State<'a> { } if let Some(ob) = self.avatar_ob { - self.network.packet_send.send(Packet::Position( - ob, - self.camera.position().into(), - self.camera.rotation().into(), - ))?; + if self.last_position_tx.elapsed().as_secs_f32() > 0.1 { + self.network.packet_send.send(Packet::Position( + ob, + self.camera.position().into(), + self.camera.rotation().into(), + ))?; + self.last_position_tx = Instant::now(); + } while let Some(p) = self.audio.pop_output() { self.network.packet_send.send(Packet::Sound(ob, Data(p)))?; } |