临时提交

This commit is contained in:
林若思 2025-12-20 16:55:48 +08:00
parent 173c610708
commit f7100ddc93
2 changed files with 29 additions and 30 deletions

View File

@ -1,6 +1,7 @@
package com.zs.smarthuman.sherpa package com.zs.smarthuman.sherpa
import android.content.res.AssetManager import android.content.res.AssetManager
import android.util.Log
class VoiceController( class VoiceController(
assetManager: AssetManager, assetManager: AssetManager,
@ -14,16 +15,16 @@ class VoiceController(
set(value) { set(value) {
field = value field = value
onStateChanged?.invoke(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) { private val wakeupManager = WakeupManager(assetManager) {
if (wakeupLocked) return@WakeupManager Log.d("VoiceController", "唤醒触发! wakeupFlag=$wakeupFlag, 当前状态=$state")
wakeupLocked = true wakeupFlag = true
wakeupTime = System.currentTimeMillis()
onWakeup() onWakeup()
startWaitSpeech() startWaitSpeech()
} }
@ -39,7 +40,6 @@ class VoiceController(
private val audioBuffer = mutableListOf<Float>() private val audioBuffer = mutableListOf<Float>()
private val preBuffer = ArrayDeque<Float>() // pre-roll 1 秒 private val preBuffer = ArrayDeque<Float>() // pre-roll 1 秒
private val PRE_BUFFER_SIZE = 16000 private val PRE_BUFFER_SIZE = 16000
private var idleTimer = 0L private var idleTimer = 0L
var isPlaying = false var isPlaying = false
@ -48,7 +48,7 @@ class VoiceController(
/** ================= 尾部静音控制 ================= */ /** ================= 尾部静音控制 ================= */
private var vadEndPending = false private var vadEndPending = false
private var vadEndTime = 0L private var vadEndTime = 0L
private val END_SILENCE_MS = 1000L // 小爱同学约 1 秒 private val END_SILENCE_MS = 1000L
/* ================= 公共接口 ================= */ /* ================= 公共接口 ================= */
fun initWakeup(keywords: String) { fun initWakeup(keywords: String) {
@ -56,7 +56,6 @@ class VoiceController(
onStateChanged?.invoke(state) onStateChanged?.invoke(state)
} }
/** 麦克风音频入口 */
fun acceptAudio(samples: FloatArray) { fun acceptAudio(samples: FloatArray) {
cachePreBuffer(samples) cachePreBuffer(samples)
@ -73,14 +72,10 @@ class VoiceController(
vadManager.accept(samples) vadManager.accept(samples)
idleTimer = System.currentTimeMillis() idleTimer = System.currentTimeMillis()
// ⭐ 如果进入准备结束状态,检查尾部静音 if (vadEndPending && System.currentTimeMillis() - vadEndTime >= END_SILENCE_MS) {
if (vadEndPending) {
val now = System.currentTimeMillis()
if (now - vadEndTime >= END_SILENCE_MS) {
finishSentence() finishSentence()
} }
} }
}
VoiceState.PLAYING -> Unit VoiceState.PLAYING -> Unit
} }
@ -93,19 +88,15 @@ class VoiceController(
fun onPlayEnd() { fun onPlayEnd() {
isPlaying = false isPlaying = false
// 播放结束,如果刚唤醒则进入等待说话,否则 reset
if (state == VoiceState.WAIT_SPEECH) return if (state == VoiceState.WAIT_SPEECH) return
reset() reset()
} }
/** 小爱式 idle 超时 */
fun checkIdleTimeout() { fun checkIdleTimeout() {
if (state != VoiceState.WAIT_SPEECH) return if (state != VoiceState.WAIT_SPEECH) return
val now = System.currentTimeMillis() val now = System.currentTimeMillis()
if (now - wakeupTime < 2000) return // 唤醒后保护 2 秒 if (now - idleTimer > idleTimeoutSeconds * 1000) {
if (now - wakeupTime > idleTimeoutSeconds * 1000) {
reset() reset()
} }
} }
@ -117,6 +108,7 @@ class VoiceController(
vadManager.reset() vadManager.reset()
wakeupManager.reset() wakeupManager.reset()
wakeupLocked = false wakeupLocked = false
wakeupFlag = false
idleTimer = 0 idleTimer = 0
vadEndPending = false vadEndPending = false
} }
@ -130,6 +122,7 @@ class VoiceController(
isPlaying = false isPlaying = false
state = VoiceState.WAIT_WAKEUP state = VoiceState.WAIT_WAKEUP
wakeupLocked = false wakeupLocked = false
wakeupFlag = false
vadEndPending = false vadEndPending = false
} }
@ -140,30 +133,35 @@ class VoiceController(
idleTimer = System.currentTimeMillis() idleTimer = System.currentTimeMillis()
} }
/** VAD 开始 */
private fun onVadSpeechStart() { private fun onVadSpeechStart() {
// 如果正在准备结束,说明用户又说话了
vadEndPending = false 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 state = VoiceState.RECORDING
audioBuffer.clear() audioBuffer.clear()
audioBuffer.addAll(preBuffer) audioBuffer.addAll(preBuffer)
idleTimer = System.currentTimeMillis() idleTimer = System.currentTimeMillis()
Log.d("VoiceController", "开始录音, 状态变为=$state")
} }
/** VAD 结束,延迟处理 */
private fun onVadSpeechEnd() { private fun onVadSpeechEnd() {
if (state != VoiceState.RECORDING) return if (state != VoiceState.RECORDING) return
vadEndPending = true vadEndPending = true
vadEndTime = System.currentTimeMillis() vadEndTime = System.currentTimeMillis()
Log.d("VoiceController", "VAD结束, 等待尾部静音")
} }
/** ⭐ 真正结束函数 */
private fun finishSentence() { private fun finishSentence() {
vadEndPending = false vadEndPending = false
state = VoiceState.WAIT_WAKEUP state = VoiceState.WAIT_WAKEUP
@ -177,6 +175,7 @@ class VoiceController(
} }
idleTimer = 0 idleTimer = 0
Log.d("VoiceController", "录音结束, 返回 WAIT_WAKEUP")
} }
private fun cachePreBuffer(samples: FloatArray) { private fun cachePreBuffer(samples: FloatArray) {

View File

@ -266,10 +266,10 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
private fun processAudio() { private fun processAudio() {
// val interval = 0.1 val interval = 0.1
// val bufferSize = (interval * sampleRateInHz).toInt() // in samples val bufferSize = (interval * sampleRateInHz).toInt() // in samples
// val buffer = ShortArray(bufferSize) // val buffer = ShortArray(bufferSize)
val bufferSize = 512 // in samples // val bufferSize = 512 // in samples
val buffer = ShortArray(bufferSize) val buffer = ShortArray(bufferSize)
while (isRecording) { while (isRecording) {
val ret = audioRecord?.read(buffer, 0, buffer.size) ?: 0 val ret = audioRecord?.read(buffer, 0, buffer.size) ?: 0
@ -329,7 +329,7 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
stopRecording() stopRecording()
voiceController?.reset() voiceController?.release()
UnityPlayerHolder.getInstance().release() UnityPlayerHolder.getInstance().release()
UnityPlayerHolder.getInstance().clearCache() UnityPlayerHolder.getInstance().clearCache()
releaseIM() releaseIM()