fix: stabilize tsclientlib audio playback buffering
This commit is contained in:
@@ -9,6 +9,7 @@ use tsproto_packets::packets::{AudioData, InAudioBuf};
|
||||
const SAMPLE_RATE: u32 = 48000;
|
||||
const CHANNELS: u16 = 2;
|
||||
const FRAME_SIZE: usize = 960; // 20ms at 48kHz mono
|
||||
const PLAYBACK_FILL_SAMPLES: usize = 1920; // 20ms at 48kHz stereo for tsclientlib playback
|
||||
const OPUS_MAX_PACKET: usize = 1275;
|
||||
|
||||
type PacketSender = std::sync::mpsc::Sender<InAudioBuf>;
|
||||
@@ -74,6 +75,8 @@ impl AudioPlayback {
|
||||
let callback_volumes = Arc::clone(&volumes);
|
||||
let callback_muted = Arc::clone(&muted_clients);
|
||||
let mut handler = AudioHandler::<ClientId>::new();
|
||||
let mut playback_chunk = vec![0.0f32; PLAYBACK_FILL_SAMPLES];
|
||||
let mut playback_chunk_offset = PLAYBACK_FILL_SAMPLES;
|
||||
|
||||
let stream = device
|
||||
.build_output_stream(
|
||||
@@ -87,9 +90,6 @@ impl AudioPlayback {
|
||||
};
|
||||
let _ = handler.handle_packet(ClientId(from), packet);
|
||||
}
|
||||
for sample in data.iter_mut() {
|
||||
*sample = 0.0;
|
||||
}
|
||||
let volumes = callback_volumes.lock().ok().map(|volumes| volumes.clone());
|
||||
let muted_clients = callback_muted.lock().ok().map(|muted| muted.clone());
|
||||
for (id, queue) in handler.get_mut_queues().iter_mut() {
|
||||
@@ -103,7 +103,25 @@ impl AudioPlayback {
|
||||
.unwrap_or(false);
|
||||
queue.volume = if muted { 0.0 } else { volume };
|
||||
}
|
||||
handler.fill_buffer(data);
|
||||
|
||||
let mut written = 0;
|
||||
while written < data.len() {
|
||||
if playback_chunk_offset >= playback_chunk.len() {
|
||||
playback_chunk.fill(0.0);
|
||||
handler.fill_buffer(&mut playback_chunk);
|
||||
playback_chunk_offset = 0;
|
||||
}
|
||||
|
||||
let available = playback_chunk.len() - playback_chunk_offset;
|
||||
let remaining = data.len() - written;
|
||||
let copy_len = available.min(remaining);
|
||||
data[written..written + copy_len].copy_from_slice(
|
||||
&playback_chunk
|
||||
[playback_chunk_offset..playback_chunk_offset + copy_len],
|
||||
);
|
||||
playback_chunk_offset += copy_len;
|
||||
written += copy_len;
|
||||
}
|
||||
},
|
||||
|err| tracing::error!("Audio output error: {err}"),
|
||||
None,
|
||||
|
||||
@@ -912,19 +912,11 @@ impl App {
|
||||
iced::Event::Keyboard(iced::keyboard::Event::KeyPressed {
|
||||
key: iced::keyboard::Key::Character(c),
|
||||
..
|
||||
}) => {
|
||||
if c.as_str().to_lowercase() == "v" {
|
||||
return Message::PttPressed;
|
||||
}
|
||||
}
|
||||
}) if c.as_str().to_lowercase() == "v" => return Message::PttPressed,
|
||||
iced::Event::Keyboard(iced::keyboard::Event::KeyReleased {
|
||||
key: iced::keyboard::Key::Character(c),
|
||||
..
|
||||
}) => {
|
||||
if c.as_str().to_lowercase() == "v" {
|
||||
return Message::PttReleased;
|
||||
}
|
||||
}
|
||||
}) if c.as_str().to_lowercase() == "v" => return Message::PttReleased,
|
||||
_ => {}
|
||||
}
|
||||
Message::Noop
|
||||
|
||||
Reference in New Issue
Block a user