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 SAMPLE_RATE: u32 = 48000;
|
||||||
const CHANNELS: u16 = 2;
|
const CHANNELS: u16 = 2;
|
||||||
const FRAME_SIZE: usize = 960; // 20ms at 48kHz mono
|
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;
|
const OPUS_MAX_PACKET: usize = 1275;
|
||||||
|
|
||||||
type PacketSender = std::sync::mpsc::Sender<InAudioBuf>;
|
type PacketSender = std::sync::mpsc::Sender<InAudioBuf>;
|
||||||
@@ -74,6 +75,8 @@ impl AudioPlayback {
|
|||||||
let callback_volumes = Arc::clone(&volumes);
|
let callback_volumes = Arc::clone(&volumes);
|
||||||
let callback_muted = Arc::clone(&muted_clients);
|
let callback_muted = Arc::clone(&muted_clients);
|
||||||
let mut handler = AudioHandler::<ClientId>::new();
|
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
|
let stream = device
|
||||||
.build_output_stream(
|
.build_output_stream(
|
||||||
@@ -87,9 +90,6 @@ impl AudioPlayback {
|
|||||||
};
|
};
|
||||||
let _ = handler.handle_packet(ClientId(from), packet);
|
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 volumes = callback_volumes.lock().ok().map(|volumes| volumes.clone());
|
||||||
let muted_clients = callback_muted.lock().ok().map(|muted| muted.clone());
|
let muted_clients = callback_muted.lock().ok().map(|muted| muted.clone());
|
||||||
for (id, queue) in handler.get_mut_queues().iter_mut() {
|
for (id, queue) in handler.get_mut_queues().iter_mut() {
|
||||||
@@ -103,7 +103,25 @@ impl AudioPlayback {
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
queue.volume = if muted { 0.0 } else { volume };
|
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}"),
|
|err| tracing::error!("Audio output error: {err}"),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -912,19 +912,11 @@ impl App {
|
|||||||
iced::Event::Keyboard(iced::keyboard::Event::KeyPressed {
|
iced::Event::Keyboard(iced::keyboard::Event::KeyPressed {
|
||||||
key: iced::keyboard::Key::Character(c),
|
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 {
|
iced::Event::Keyboard(iced::keyboard::Event::KeyReleased {
|
||||||
key: iced::keyboard::Key::Character(c),
|
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
|
Message::Noop
|
||||||
|
|||||||
Reference in New Issue
Block a user