Refactor audio channel handling and wake word detection in Application class (#1722)
- Introduced ContinueOpenAudioChannel and ContinueWakeWordInvoke methods to streamline audio channel management and wake word processing. - Updated HandleToggleChatEvent and HandleWakeWordDetectedEvent to utilize scheduling for state changes, improving UI responsiveness. - Simplified logic for setting listening modes based on audio channel state, enhancing code clarity and maintainability.
This commit is contained in:
@ -691,14 +691,16 @@ void Application::HandleToggleChatEvent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state == kDeviceStateIdle) {
|
if (state == kDeviceStateIdle) {
|
||||||
|
ListeningMode mode = aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime;
|
||||||
if (!protocol_->IsAudioChannelOpened()) {
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
// Schedule to let the state change be processed first (UI update)
|
||||||
|
Schedule([this, mode]() {
|
||||||
|
ContinueOpenAudioChannel(mode);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
SetListeningMode(mode);
|
||||||
|
|
||||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
|
||||||
} else if (state == kDeviceStateSpeaking) {
|
} else if (state == kDeviceStateSpeaking) {
|
||||||
AbortSpeaking(kAbortReasonNone);
|
AbortSpeaking(kAbortReasonNone);
|
||||||
} else if (state == kDeviceStateListening) {
|
} else if (state == kDeviceStateListening) {
|
||||||
@ -706,6 +708,21 @@ void Application::HandleToggleChatEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::ContinueOpenAudioChannel(ListeningMode mode) {
|
||||||
|
// Check state again in case it was changed during scheduling
|
||||||
|
if (GetDeviceState() != kDeviceStateConnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
|
if (!protocol_->OpenAudioChannel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetListeningMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::HandleStartListeningEvent() {
|
void Application::HandleStartListeningEvent() {
|
||||||
auto state = GetDeviceState();
|
auto state = GetDeviceState();
|
||||||
|
|
||||||
@ -726,11 +743,12 @@ void Application::HandleStartListeningEvent() {
|
|||||||
if (state == kDeviceStateIdle) {
|
if (state == kDeviceStateIdle) {
|
||||||
if (!protocol_->IsAudioChannelOpened()) {
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
// Schedule to let the state change be processed first (UI update)
|
||||||
|
Schedule([this]() {
|
||||||
|
ContinueOpenAudioChannel(kListeningModeManualStop);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SetListeningMode(kListeningModeManualStop);
|
SetListeningMode(kListeningModeManualStop);
|
||||||
} else if (state == kDeviceStateSpeaking) {
|
} else if (state == kDeviceStateSpeaking) {
|
||||||
AbortSpeaking(kAbortReasonNone);
|
AbortSpeaking(kAbortReasonNone);
|
||||||
@ -762,16 +780,40 @@ void Application::HandleWakeWordDetectedEvent() {
|
|||||||
|
|
||||||
if (state == kDeviceStateIdle) {
|
if (state == kDeviceStateIdle) {
|
||||||
audio_service_.EncodeWakeWord();
|
audio_service_.EncodeWakeWord();
|
||||||
|
auto wake_word = audio_service_.GetLastWakeWord();
|
||||||
|
|
||||||
if (!protocol_->IsAudioChannelOpened()) {
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
|
// Schedule to let the state change be processed first (UI update),
|
||||||
|
// then continue with OpenAudioChannel which may block for ~1 second
|
||||||
|
Schedule([this, wake_word]() {
|
||||||
|
ContinueWakeWordInvoke(wake_word);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Channel already opened, continue directly
|
||||||
|
ContinueWakeWordInvoke(wake_word);
|
||||||
|
} else if (state == kDeviceStateSpeaking) {
|
||||||
|
AbortSpeaking(kAbortReasonWakeWordDetected);
|
||||||
|
} else if (state == kDeviceStateActivating) {
|
||||||
|
// Restart the activation check if the wake word is detected during activation
|
||||||
|
SetDeviceState(kDeviceStateIdle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::ContinueWakeWordInvoke(const std::string& wake_word) {
|
||||||
|
// Check state again in case it was changed during scheduling
|
||||||
|
if (GetDeviceState() != kDeviceStateConnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
if (!protocol_->OpenAudioChannel()) {
|
||||||
audio_service_.EnableWakeWordDetection(true);
|
audio_service_.EnableWakeWordDetection(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto wake_word = audio_service_.GetLastWakeWord();
|
|
||||||
ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str());
|
ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str());
|
||||||
#if CONFIG_SEND_WAKE_WORD_DATA
|
#if CONFIG_SEND_WAKE_WORD_DATA
|
||||||
// Encode and send the wake word data to the server
|
// Encode and send the wake word data to the server
|
||||||
@ -787,12 +829,6 @@ void Application::HandleWakeWordDetectedEvent() {
|
|||||||
play_popup_on_listening_ = true;
|
play_popup_on_listening_ = true;
|
||||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
||||||
#endif
|
#endif
|
||||||
} else if (state == kDeviceStateSpeaking) {
|
|
||||||
AbortSpeaking(kAbortReasonWakeWordDetected);
|
|
||||||
} else if (state == kDeviceStateActivating) {
|
|
||||||
// Restart the activation check if the wake word is detected during activation
|
|
||||||
SetDeviceState(kDeviceStateIdle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::HandleStateChangedEvent() {
|
void Application::HandleStateChangedEvent() {
|
||||||
@ -960,27 +996,14 @@ void Application::WakeWordInvoke(const std::string& wake_word) {
|
|||||||
|
|
||||||
if (!protocol_->IsAudioChannelOpened()) {
|
if (!protocol_->IsAudioChannelOpened()) {
|
||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
// Schedule to let the state change be processed first (UI update)
|
||||||
audio_service_.EnableWakeWordDetection(true);
|
Schedule([this, wake_word]() {
|
||||||
|
ContinueWakeWordInvoke(wake_word);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
// Channel already opened, continue directly
|
||||||
|
ContinueWakeWordInvoke(wake_word);
|
||||||
ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str());
|
|
||||||
#if CONFIG_USE_AFE_WAKE_WORD || CONFIG_USE_CUSTOM_WAKE_WORD
|
|
||||||
// Encode and send the wake word data to the server
|
|
||||||
while (auto packet = audio_service_.PopWakeWordPacket()) {
|
|
||||||
protocol_->SendAudio(std::move(packet));
|
|
||||||
}
|
|
||||||
// Set the chat state to wake word detected
|
|
||||||
protocol_->SendWakeWordDetected(wake_word);
|
|
||||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
|
||||||
#else
|
|
||||||
// Set flag to play popup sound after state changes to listening
|
|
||||||
// (PlaySound here would be cleared by ResetDecoder in EnableVoiceProcessing)
|
|
||||||
play_popup_on_listening_ = true;
|
|
||||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
|
||||||
#endif
|
|
||||||
} else if (state == kDeviceStateSpeaking) {
|
} else if (state == kDeviceStateSpeaking) {
|
||||||
Schedule([this]() {
|
Schedule([this]() {
|
||||||
AbortSpeaking(kAbortReasonNone);
|
AbortSpeaking(kAbortReasonNone);
|
||||||
|
|||||||
@ -153,6 +153,8 @@ private:
|
|||||||
void HandleNetworkDisconnectedEvent();
|
void HandleNetworkDisconnectedEvent();
|
||||||
void HandleActivationDoneEvent();
|
void HandleActivationDoneEvent();
|
||||||
void HandleWakeWordDetectedEvent();
|
void HandleWakeWordDetectedEvent();
|
||||||
|
void ContinueOpenAudioChannel(ListeningMode mode);
|
||||||
|
void ContinueWakeWordInvoke(const std::string& wake_word);
|
||||||
|
|
||||||
// Activation task (runs in background)
|
// Activation task (runs in background)
|
||||||
void ActivationTask();
|
void ActivationTask();
|
||||||
|
|||||||
Reference in New Issue
Block a user