fix(audio): eliminate Android output stutter via Oboe config + lock-free callback (#20)
* fix(audio): eliminate Android output stutter via Oboe config + lock-free callback Phase 1 — Oboe configuration: - Change output stream from Usage::VoiceCommunication to Usage::Game with ContentType::Sonification to avoid forcing the Legacy (OpenSL ES) data path on most devices (Oboe issue #2075) - Switch output format from i16 Mono to f32 Stereo, matching Qint's proven configuration and eliminating per-callback downmix conversion - Set buffer size to 2x burst after stream open, reducing default buffer from 8-20x burst to 2x burst for lower latency - Remove scratch Mutex<Vec<f32>>; callback writes directly to Oboe buffer Phase 2 — Lock-free output callback: - Add audio_event_queue.rs: lock-free SPSC bridge using crossbeam ArrayQueue with separate packet (lossy) and control (reliable) channels - OutputCallback now owns AudioHandler directly (no Arc<Mutex<>> on Android) - Inbound forwarder pushes packets via AudioEventProducer (no mutex) - set_client_volume pushes control commands via event queue on Android - iOS/desktop Arc<Mutex<AudioHandler>> path unchanged * fix(audio): address PR #20 review findings - Store AudioEventConsumer directly in OutputCallback to eliminate per-callback Arc clone on the real-time audio thread - Add SAFETY comment for the unsafe from_raw_parts_mut transmute - Bound set_client_volume spin-loop to 64 retries with warn log - Remove redundant crossbeam-utils direct dependency - Regenerate license inventory for new crossbeam deps (CI fix) * fix(audio): use ASCII TODO punctuation
This commit is contained in:
@@ -67,7 +67,7 @@ pub type BackendEventTx = mpsc::UnboundedSender<BackendEvent>;
|
||||
pub type AudioSessionId = i32;
|
||||
|
||||
/// Engine-owned state shared with mobile voice audio callbacks.
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(not(target_os = "android"), derive(Clone))]
|
||||
pub(crate) struct VoiceAudioParams {
|
||||
/// Opus-encoded voice packets sent on this channel toward the
|
||||
/// protocol layer.
|
||||
@@ -78,8 +78,15 @@ pub(crate) struct VoiceAudioParams {
|
||||
pub frames_sent: Arc<AtomicU32>,
|
||||
/// Pre-encode amplitude scale (1.0 = unity).
|
||||
pub mic_gain: f32,
|
||||
/// AudioHandler owned by the Android output callback.
|
||||
#[cfg(target_os = "android")]
|
||||
pub handler: AudioHandler<SessionAudioId>,
|
||||
/// Producer used by Android engine tasks to feed the output callback.
|
||||
#[cfg(target_os = "android")]
|
||||
pub event_producer: crate::audio_event_queue::AudioEventProducer,
|
||||
/// AudioHandler that inbound decode+mix feeds into; the output
|
||||
/// callback pulls mixed stereo f32 from it.
|
||||
#[cfg(not(target_os = "android"))]
|
||||
pub handler: Arc<Mutex<AudioHandler<SessionAudioId>>>,
|
||||
/// Master output gain (f32 bits stored in AtomicU32 for lock-free
|
||||
/// cross-thread read from the realtime audio callback).
|
||||
|
||||
Reference in New Issue
Block a user