simplify Live Call audio: remove MODE_IN_COMMUNICATION
MODE_IN_COMMUNICATION activates the telephony DSP pipeline which degrades audio quality and requires setCommunicationDevice hacks for speaker routing. The Gemini reference implementation doesn't use it. Echo protection now relies on: 1. VOICE_COMMUNICATION AudioSource (built-in AEC/AGC/NS) 2. AcousticEchoCanceler on AudioRecord session (hardware AEC) 3. Hard ducking (zero mic chunks during model speech) AudioTrack stays USAGE_ASSISTANT for full-quality speaker output. This matches the WebRTC.ventures Gemini prototype architecture.
This commit is contained in:
parent
b254862ef1
commit
965f1876bf
2 changed files with 0 additions and 34 deletions
|
|
@ -5,7 +5,6 @@ import android.content.Context
|
|||
import android.content.pm.PackageManager
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioFormat
|
||||
import android.media.AudioManager
|
||||
import android.media.AudioRecord
|
||||
import android.media.AudioTrack
|
||||
import android.media.MediaRecorder
|
||||
|
|
@ -52,8 +51,6 @@ class AudioPipeline(private val context: Context) {
|
|||
var onChunk: ((base64Pcm: String) -> Unit)? = null
|
||||
var onAmplitude: ((Float) -> Unit)? = null
|
||||
|
||||
private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
private var previousAudioMode = AudioManager.MODE_NORMAL
|
||||
private var recorder: AudioRecord? = null
|
||||
private var track: AudioTrack? = null
|
||||
private var aec: AcousticEchoCanceler? = null
|
||||
|
|
@ -62,35 +59,6 @@ class AudioPipeline(private val context: Context) {
|
|||
@Volatile private var ducking = false
|
||||
@Volatile private var capturing = false
|
||||
|
||||
// ─── Audio Mode ───────────────────────────────────────────────────────
|
||||
|
||||
fun enterCallMode() {
|
||||
previousAudioMode = audioManager.mode
|
||||
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
val speaker = audioManager.availableCommunicationDevices
|
||||
.firstOrNull { it.type == android.media.AudioDeviceInfo.TYPE_BUILTIN_SPEAKER }
|
||||
if (speaker != null) {
|
||||
audioManager.setCommunicationDevice(speaker)
|
||||
Log.i(TAG, "Communication device → speaker")
|
||||
}
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
audioManager.isSpeakerphoneOn = true
|
||||
}
|
||||
}
|
||||
|
||||
fun exitCallMode() {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 31) {
|
||||
audioManager.clearCommunicationDevice()
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
audioManager.isSpeakerphoneOn = false
|
||||
}
|
||||
audioManager.mode = previousAudioMode
|
||||
}
|
||||
|
||||
// ─── Capture ──────────────────────────────────────────────────────────
|
||||
|
||||
fun startCapture(scope: CoroutineScope): Boolean {
|
||||
|
|
@ -243,7 +211,6 @@ class AudioPipeline(private val context: Context) {
|
|||
fun release() {
|
||||
stopCapture()
|
||||
stopPlayback()
|
||||
exitCallMode()
|
||||
}
|
||||
|
||||
// ─── Helpers ──────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ class LiveCallService : Service() {
|
|||
connectTimeoutJob?.cancel()
|
||||
_status.value = CallStatus.LISTENING
|
||||
|
||||
pipeline.enterCallMode()
|
||||
if (!pipeline.initPlayback()) {
|
||||
Log.e(TAG, "Playback init failed")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue