optimize Live Call latency: 50ms chunks, smaller playback buffer

- Capture chunks 100ms → 50ms: halves input latency, model hears
  speech 50ms sooner per chunk
- Playback buffer minBuf*4 → minBuf*2: reduces output buffering
  delay while LOW_LATENCY mode keeps playback glitch-free
This commit is contained in:
Bruno Deanoz 2026-06-24 14:00:52 +02:00
parent 965f1876bf
commit 70b91cc7bb

View file

@ -20,15 +20,14 @@ import kotlin.math.sqrt
/**
* Bidirectional audio pipeline for Live Call.
*
* Capture: AudioRecord (16kHz PCM16 mono, VOICE_COMMUNICATION for hardware AEC)
* 100ms chunks Base64 [onChunk] callback.
* Capture: AudioRecord (16kHz PCM16 mono, VOICE_COMMUNICATION + AEC)
* 50ms chunks Base64 [onChunk] callback.
*
* Playback: AudioTrack (24kHz PCM16 mono, LOW_LATENCY, MODE_STREAM)
* PCM16 chunks from server.
*
* Mic-ducking: gain reduced to 10% while the KI speaks (prevents echo feedback
* loop on devices with weak AEC). Not a digital gain we skip sending chunks
* whose RMS is below the ducking threshold.
* Echo prevention: AcousticEchoCanceler (hardware) + hard ducking
* (zero mic chunks while model speaks).
*/
class AudioPipeline(private val context: Context) {
@ -41,11 +40,9 @@ class AudioPipeline(private val context: Context) {
private const val CHANNEL_OUT = AudioFormat.CHANNEL_OUT_MONO
private const val ENCODING = AudioFormat.ENCODING_PCM_16BIT
private const val CHUNK_MS = 100
private const val CAPTURE_CHUNK_SAMPLES = CAPTURE_SAMPLE_RATE * CHUNK_MS / 1000 // 1600
private const val CAPTURE_CHUNK_BYTES = CAPTURE_CHUNK_SAMPLES * 2 // 3200
private const val DUCKING_GAIN = 0.10f
private const val CHUNK_MS = 50
private const val CAPTURE_CHUNK_SAMPLES = CAPTURE_SAMPLE_RATE * CHUNK_MS / 1000 // 800
private const val CAPTURE_CHUNK_BYTES = CAPTURE_CHUNK_SAMPLES * 2 // 1600
}
var onChunk: ((base64Pcm: String) -> Unit)? = null
@ -164,7 +161,7 @@ class AudioPipeline(private val context: Context) {
.setChannelMask(CHANNEL_OUT)
.build()
)
.setBufferSizeInBytes(maxOf(minBuf * 4, 24_000 * 2))
.setBufferSizeInBytes(maxOf(minBuf * 2, 24_000))
.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY)
.setTransferMode(AudioTrack.MODE_STREAM)
.build()