From f7100ddc93c5b453a6d94d8728c511bc7ea21429 Mon Sep 17 00:00:00 2001 From: ross <3024454314@qq.com> Date: Sat, 20 Dec 2025 16:55:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zs/smarthuman/sherpa/VoiceController.kt | 51 +++++++++---------- .../java/com/zs/smarthuman/ui/MainActivity.kt | 8 +-- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/zs/smarthuman/sherpa/VoiceController.kt b/app/src/main/java/com/zs/smarthuman/sherpa/VoiceController.kt index c45712e..6860f54 100644 --- a/app/src/main/java/com/zs/smarthuman/sherpa/VoiceController.kt +++ b/app/src/main/java/com/zs/smarthuman/sherpa/VoiceController.kt @@ -1,6 +1,7 @@ package com.zs.smarthuman.sherpa import android.content.res.AssetManager +import android.util.Log class VoiceController( assetManager: AssetManager, @@ -14,16 +15,16 @@ class VoiceController( set(value) { field = value onStateChanged?.invoke(value) + Log.d("VoiceController", "当前状态: $value") } /** ================= 唤醒 ================= */ - private var wakeupTime = 0L // 唤醒时间 - private var wakeupLocked = false // 防连击 + private var wakeupLocked = false + private var wakeupFlag = false private val wakeupManager = WakeupManager(assetManager) { - if (wakeupLocked) return@WakeupManager - wakeupLocked = true - wakeupTime = System.currentTimeMillis() + Log.d("VoiceController", "唤醒触发! wakeupFlag=$wakeupFlag, 当前状态=$state") + wakeupFlag = true onWakeup() startWaitSpeech() } @@ -39,7 +40,6 @@ class VoiceController( private val audioBuffer = mutableListOf() private val preBuffer = ArrayDeque() // pre-roll 1 秒 private val PRE_BUFFER_SIZE = 16000 - private var idleTimer = 0L var isPlaying = false @@ -48,7 +48,7 @@ class VoiceController( /** ================= 尾部静音控制 ================= */ private var vadEndPending = false private var vadEndTime = 0L - private val END_SILENCE_MS = 1000L // 小爱同学约 1 秒 + private val END_SILENCE_MS = 1000L /* ================= 公共接口 ================= */ fun initWakeup(keywords: String) { @@ -56,7 +56,6 @@ class VoiceController( onStateChanged?.invoke(state) } - /** 麦克风音频入口 */ fun acceptAudio(samples: FloatArray) { cachePreBuffer(samples) @@ -73,12 +72,8 @@ class VoiceController( vadManager.accept(samples) idleTimer = System.currentTimeMillis() - // ⭐ 如果进入准备结束状态,检查尾部静音 - if (vadEndPending) { - val now = System.currentTimeMillis() - if (now - vadEndTime >= END_SILENCE_MS) { - finishSentence() - } + if (vadEndPending && System.currentTimeMillis() - vadEndTime >= END_SILENCE_MS) { + finishSentence() } } @@ -93,19 +88,15 @@ class VoiceController( fun onPlayEnd() { isPlaying = false - // 播放结束,如果刚唤醒则进入等待说话,否则 reset if (state == VoiceState.WAIT_SPEECH) return reset() } - /** 小爱式 idle 超时 */ fun checkIdleTimeout() { if (state != VoiceState.WAIT_SPEECH) return val now = System.currentTimeMillis() - if (now - wakeupTime < 2000) return // 唤醒后保护 2 秒 - - if (now - wakeupTime > idleTimeoutSeconds * 1000) { + if (now - idleTimer > idleTimeoutSeconds * 1000) { reset() } } @@ -117,6 +108,7 @@ class VoiceController( vadManager.reset() wakeupManager.reset() wakeupLocked = false + wakeupFlag = false idleTimer = 0 vadEndPending = false } @@ -130,6 +122,7 @@ class VoiceController( isPlaying = false state = VoiceState.WAIT_WAKEUP wakeupLocked = false + wakeupFlag = false vadEndPending = false } @@ -140,30 +133,35 @@ class VoiceController( idleTimer = System.currentTimeMillis() } - /** VAD 开始 */ private fun onVadSpeechStart() { - // 如果正在准备结束,说明用户又说话了 vadEndPending = false - if (state != VoiceState.WAIT_SPEECH) return + Log.d("VoiceController", "VAD开始, 当前状态=$state, wakeupFlag=$wakeupFlag") - // 丢弃唤醒词音频 - if (wakeupManager.consumeWakeupFlag()) return + // 如果是唤醒词音频则丢弃 + if (wakeupFlag) { + wakeupFlag = false + Log.d("VoiceController", "丢弃唤醒词音频") + return + } + + if (state != VoiceState.WAIT_SPEECH) return state = VoiceState.RECORDING audioBuffer.clear() audioBuffer.addAll(preBuffer) idleTimer = System.currentTimeMillis() + + Log.d("VoiceController", "开始录音, 状态变为=$state") } - /** VAD 结束,延迟处理 */ private fun onVadSpeechEnd() { if (state != VoiceState.RECORDING) return vadEndPending = true vadEndTime = System.currentTimeMillis() + Log.d("VoiceController", "VAD结束, 等待尾部静音") } - /** ⭐ 真正结束函数 */ private fun finishSentence() { vadEndPending = false state = VoiceState.WAIT_WAKEUP @@ -177,6 +175,7 @@ class VoiceController( } idleTimer = 0 + Log.d("VoiceController", "录音结束, 返回 WAIT_WAKEUP") } private fun cachePreBuffer(samples: FloatArray) { diff --git a/app/src/main/java/com/zs/smarthuman/ui/MainActivity.kt b/app/src/main/java/com/zs/smarthuman/ui/MainActivity.kt index 3a96f9b..f4f16c6 100644 --- a/app/src/main/java/com/zs/smarthuman/ui/MainActivity.kt +++ b/app/src/main/java/com/zs/smarthuman/ui/MainActivity.kt @@ -266,10 +266,10 @@ class MainActivity : BaseViewModelActivity() private fun processAudio() { -// val interval = 0.1 -// val bufferSize = (interval * sampleRateInHz).toInt() // in samples + val interval = 0.1 + val bufferSize = (interval * sampleRateInHz).toInt() // in samples // val buffer = ShortArray(bufferSize) - val bufferSize = 512 // in samples +// val bufferSize = 512 // in samples val buffer = ShortArray(bufferSize) while (isRecording) { val ret = audioRecord?.read(buffer, 0, buffer.size) ?: 0 @@ -329,7 +329,7 @@ class MainActivity : BaseViewModelActivity() override fun onDestroy() { super.onDestroy() stopRecording() - voiceController?.reset() + voiceController?.release() UnityPlayerHolder.getInstance().release() UnityPlayerHolder.getInstance().clearCache() releaseIM()