@@ -123,20 +123,52 @@ void Application::ToggleChatState() {
123
123
Schedule ([this ]() {
124
124
if (chat_state_ == kChatStateIdle ) {
125
125
SetChatState (kChatStateConnecting );
126
- if (protocol_->OpenAudioChannel ()) {
127
- opus_encoder_.ResetState ();
128
- SetChatState (kChatStateListening );
129
- } else {
126
+ if (!protocol_->OpenAudioChannel ()) {
127
+ ESP_LOGE (TAG, " Failed to open audio channel" );
130
128
SetChatState (kChatStateIdle );
129
+ return ;
131
130
}
131
+
132
+ keep_listening_ = true ;
133
+ protocol_->SendStartListening (kListeningModeAutoStop );
134
+ SetChatState (kChatStateListening );
132
135
} else if (chat_state_ == kChatStateSpeaking ) {
133
- AbortSpeaking ();
136
+ AbortSpeaking (kAbortReasonNone );
134
137
} else if (chat_state_ == kChatStateListening ) {
135
138
protocol_->CloseAudioChannel ();
136
139
}
137
140
});
138
141
}
139
142
143
+ void Application::StartListening () {
144
+ Schedule ([this ]() {
145
+ keep_listening_ = false ;
146
+ if (chat_state_ == kChatStateIdle ) {
147
+ if (!protocol_->IsAudioChannelOpened ()) {
148
+ SetChatState (kChatStateConnecting );
149
+ if (!protocol_->OpenAudioChannel ()) {
150
+ SetChatState (kChatStateIdle );
151
+ ESP_LOGE (TAG, " Failed to open audio channel" );
152
+ return ;
153
+ }
154
+ }
155
+ protocol_->SendStartListening (kListeningModeManualStop );
156
+ SetChatState (kChatStateListening );
157
+ } else if (chat_state_ == kChatStateSpeaking ) {
158
+ AbortSpeaking (kAbortReasonNone );
159
+ protocol_->SendStartListening (kListeningModeManualStop );
160
+ SetChatState (kChatStateListening );
161
+ }
162
+ });
163
+ }
164
+
165
+ void Application::StopListening () {
166
+ Schedule ([this ]() {
167
+ protocol_->SendStopListening ();
168
+ SetChatState (kChatStateIdle );
169
+ });
170
+ }
171
+
140
172
void Application::Start () {
141
173
auto & board = Board::GetInstance ();
142
174
board.Initialize ();
@@ -248,26 +280,31 @@ void Application::Start() {
248
280
});
249
281
});
250
282
251
- wake_word_detect_.OnWakeWordDetected ([this ]() {
252
- Schedule ([this ]() {
283
+ wake_word_detect_.OnWakeWordDetected ([this ](const std::string& wake_word ) {
284
+ Schedule ([this , &wake_word ]() {
253
285
if (chat_state_ == kChatStateIdle ) {
254
286
SetChatState (kChatStateConnecting );
255
287
wake_word_detect_.EncodeWakeWordData ();
256
288
257
- if (protocol_->OpenAudioChannel ()) {
258
- std::string opus;
259
- // Encode and send the wake word data to the server
260
- while (wake_word_detect_.GetWakeWordOpus (opus)) {
261
- protocol_->SendAudio (opus);
262
- }
263
- opus_encoder_.ResetState ();
264
- // Send a ready message to indicate the server that the wake word data is sent
265
- SetChatState (kChatStateWakeWordDetected );
266
- } else {
289
+ if (!protocol_->OpenAudioChannel ()) {
290
+ ESP_LOGE (TAG, " Failed to open audio channel" );
267
291
SetChatState (kChatStateIdle );
292
+ wake_word_detect_.StartDetection ();
293
+ return ;
268
294
}
295
+
296
+ std::string opus;
297
+ // Encode and send the wake word data to the server
298
+ while (wake_word_detect_.GetWakeWordOpus (opus)) {
299
+ protocol_->SendAudio (opus);
300
+ }
301
+ // Set the chat state to wake word detected
302
+ protocol_->SendWakeWordDetected (wake_word);
303
+ ESP_LOGI (TAG, " Wake word detected: %s" , wake_word.c_str ());
304
+ keep_listening_ = true ;
305
+ SetChatState (kChatStateListening );
269
306
} else if (chat_state_ == kChatStateSpeaking ) {
270
- AbortSpeaking ();
307
+ AbortSpeaking (kAbortReasonWakeWordDetected );
271
308
}
272
309
273
310
// Resume detection
@@ -313,15 +350,23 @@ void Application::Start() {
313
350
auto state = cJSON_GetObjectItem (root, " state" );
314
351
if (strcmp (state->valuestring , " start" ) == 0 ) {
315
352
Schedule ([this ]() {
316
- skip_to_end_ = false ;
317
- SetChatState (kChatStateSpeaking );
353
+ if (chat_state_ == kChatStateIdle || chat_state_ == kChatStateListening ) {
354
+ skip_to_end_ = false ;
355
+ opus_decoder_ctl (opus_decoder_, OPUS_RESET_STATE);
356
+ SetChatState (kChatStateSpeaking );
357
+ }
318
358
});
319
359
} else if (strcmp (state->valuestring , " stop" ) == 0 ) {
320
360
Schedule ([this ]() {
321
361
auto codec = Board::GetInstance ().GetAudioCodec ();
322
362
codec->WaitForOutputDone ();
323
363
if (chat_state_ == kChatStateSpeaking ) {
324
- SetChatState (kChatStateListening );
364
+ if (keep_listening_) {
365
+ protocol_->SendStartListening (kListeningModeAutoStop );
366
+ SetChatState (kChatStateListening );
367
+ } else {
368
+ SetChatState (kChatStateIdle );
369
+ }
325
370
}
326
371
});
327
372
} else if (strcmp (state->valuestring , " sentence_start" ) == 0 ) {
@@ -375,9 +420,9 @@ void Application::MainLoop() {
375
420
}
376
421
}
377
422
378
- void Application::AbortSpeaking () {
423
+ void Application::AbortSpeaking (AbortReason reason ) {
379
424
ESP_LOGI (TAG, " Abort speaking" );
380
- protocol_->SendAbort ( );
425
+ protocol_->SendAbortSpeaking (reason );
381
426
382
427
skip_to_end_ = true ;
383
428
auto codec = Board::GetInstance ().GetAudioCodec ();
@@ -391,20 +436,17 @@ void Application::SetChatState(ChatState state) {
391
436
" connecting" ,
392
437
" listening" ,
393
438
" speaking" ,
394
- " wake_word_detected" ,
395
439
" upgrading" ,
396
440
" invalid_state"
397
441
};
398
442
if (chat_state_ == state) {
399
443
// No need to update the state
400
444
return ;
401
445
}
402
- chat_state_ = state;
403
- ESP_LOGI (TAG, " STATE: %s" , state_str[chat_state_]);
404
446
405
447
auto display = Board::GetInstance ().GetDisplay ();
406
448
auto builtin_led = Board::GetInstance ().GetBuiltinLed ();
407
- switch (chat_state_ ) {
449
+ switch (state ) {
408
450
case kChatStateUnknown :
409
451
case kChatStateIdle :
410
452
builtin_led->TurnOff ();
@@ -424,6 +466,7 @@ void Application::SetChatState(ChatState state) {
424
466
builtin_led->TurnOn ();
425
467
display->SetStatus (" 聆听中..." );
426
468
display->SetEmotion (" neutral" );
469
+ opus_encoder_.ResetState ();
427
470
#ifdef CONFIG_USE_AFE_SR
428
471
audio_processor_.Start ();
429
472
#endif
@@ -436,17 +479,17 @@ void Application::SetChatState(ChatState state) {
436
479
audio_processor_.Stop ();
437
480
#endif
438
481
break ;
439
- case kChatStateWakeWordDetected :
440
- builtin_led->SetBlue ();
441
- builtin_led->TurnOn ();
442
- break ;
443
482
case kChatStateUpgrading :
444
483
builtin_led->SetGreen ();
445
484
builtin_led->StartContinuousBlink (100 );
446
485
break ;
486
+ default :
487
+ ESP_LOGE (TAG, " Invalid chat state: %d" , chat_state_);
488
+ return ;
447
489
}
448
490
449
- protocol_->SendState (state_str[chat_state_]);
491
+ chat_state_ = state;
492
+ ESP_LOGI (TAG, " STATE: %s" , state_str[chat_state_]);
450
493
}
451
494
452
495
void Application::AudioEncodeTask () {
0 commit comments