临时提交

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
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<Float>()
private val preBuffer = ArrayDeque<Float>() // 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) {

View File

@ -266,10 +266,10 @@ class MainActivity : BaseViewModelActivity<ActivityMainBinding, MainViewModel>()
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<ActivityMainBinding, MainViewModel>()
override fun onDestroy() {
super.onDestroy()
stopRecording()
voiceController?.reset()
voiceController?.release()
UnityPlayerHolder.getInstance().release()
UnityPlayerHolder.getInstance().clearCache()
releaseIM()