临时提交
This commit is contained in:
parent
173c610708
commit
f7100ddc93
@ -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,12 +72,8 @@ class VoiceController(
|
|||||||
vadManager.accept(samples)
|
vadManager.accept(samples)
|
||||||
idleTimer = System.currentTimeMillis()
|
idleTimer = System.currentTimeMillis()
|
||||||
|
|
||||||
// ⭐ 如果进入准备结束状态,检查尾部静音
|
if (vadEndPending && System.currentTimeMillis() - vadEndTime >= END_SILENCE_MS) {
|
||||||
if (vadEndPending) {
|
finishSentence()
|
||||||
val now = System.currentTimeMillis()
|
|
||||||
if (now - vadEndTime >= END_SILENCE_MS) {
|
|
||||||
finishSentence()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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) {
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user