chore(repo): keep only current main snapshot
History squashed to one root commit to permanently drop old branch history and objects.
This commit is contained in:
154
components/domain/src/voice_interaction_tasks.c
Normal file
154
components/domain/src/voice_interaction_tasks.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "voice_interaction_internal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_audio_enc.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "voice_interaction";
|
||||
|
||||
void voice_uplink_task(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
bool low_stack_warned = false;
|
||||
UBaseType_t start_hwm = uxTaskGetStackHighWaterMark(NULL);
|
||||
ESP_LOGI(TAG, "[stage] uplink_task_started: stack_hwm_words=%u", (unsigned)start_hwm);
|
||||
|
||||
while (true) {
|
||||
if (!low_stack_warned) {
|
||||
UBaseType_t hwm = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (hwm < 256) {
|
||||
low_stack_warned = true;
|
||||
ESP_LOGW(TAG, "[stage] uplink_task_low_stack: hwm_words=%u", (unsigned)hwm);
|
||||
}
|
||||
}
|
||||
|
||||
bool active = false;
|
||||
bool connected = false;
|
||||
bool started = false;
|
||||
bool tap_active = false;
|
||||
bool listening = false;
|
||||
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
active = s_voice.session_active && !s_voice.stop_requested;
|
||||
connected = s_voice.ws_connected;
|
||||
started = s_voice.started;
|
||||
tap_active = s_voice.tap_active;
|
||||
listening = (s_voice.dialog_state == VOICE_DIALOG_STATE_LISTENING);
|
||||
voice_unlock();
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(connected && started && listening && tap_active)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
continue;
|
||||
}
|
||||
|
||||
char read_err[64] = {0};
|
||||
esp_err_t rc = voice_audio_read_pcm(s_voice.pcm_tx_buf,
|
||||
(size_t)s_voice.opus_enc_in_size / VOICE_SAMPLE_BYTES,
|
||||
VOICE_AUDIO_IO_TIMEOUT_MS,
|
||||
read_err,
|
||||
sizeof(read_err));
|
||||
if (rc != ESP_OK) {
|
||||
memset(s_voice.pcm_tx_buf, 0, (size_t)s_voice.opus_enc_in_size);
|
||||
}
|
||||
|
||||
esp_audio_enc_in_frame_t in_frame = {
|
||||
.buffer = (uint8_t *)s_voice.pcm_tx_buf,
|
||||
.len = (uint32_t)s_voice.opus_enc_in_size,
|
||||
};
|
||||
esp_audio_enc_out_frame_t out_frame = {
|
||||
.buffer = s_voice.opus_tx_buf,
|
||||
.len = (uint32_t)s_voice.opus_enc_out_size,
|
||||
.encoded_bytes = 0,
|
||||
};
|
||||
|
||||
esp_audio_err_t enc_err = esp_opus_enc_process(s_voice.opus_enc, &in_frame, &out_frame);
|
||||
if (enc_err != ESP_AUDIO_ERR_OK || out_frame.encoded_bytes == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
esp_websocket_client_handle_t ws = s_voice.ws;
|
||||
bool ws_connected = s_voice.ws_connected;
|
||||
voice_unlock();
|
||||
|
||||
bool transport_connected = (ws != NULL) && esp_websocket_client_is_connected(ws);
|
||||
if (ws_connected && !transport_connected && voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
if (s_voice.ws_connected) {
|
||||
s_voice.ws_connected = false;
|
||||
s_voice.started = false;
|
||||
s_voice.tap_active = false;
|
||||
s_voice.dialog_state = VOICE_DIALOG_STATE_IDLE;
|
||||
s_voice.last_event_ms = voice_now_ms();
|
||||
ESP_LOGW(TAG, "[stage] uplink_detected_ws_disconnected");
|
||||
}
|
||||
voice_unlock();
|
||||
}
|
||||
|
||||
if (ws != NULL && ws_connected && transport_connected) {
|
||||
int ret = esp_websocket_client_send_bin(ws,
|
||||
(const char *)s_voice.opus_tx_buf,
|
||||
(int)out_frame.encoded_bytes,
|
||||
pdMS_TO_TICKS(VOICE_WS_SEND_TIMEOUT_MS));
|
||||
if (ret >= 0) {
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
s_voice.upstream_packets++;
|
||||
s_voice.last_event_ms = voice_now_ms();
|
||||
voice_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool delete_with_caps = false;
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
delete_with_caps = s_voice.uplink_task_with_caps;
|
||||
s_voice.uplink_task = NULL;
|
||||
s_voice.uplink_task_with_caps = false;
|
||||
voice_unlock();
|
||||
}
|
||||
voice_delete_self_task(delete_with_caps);
|
||||
}
|
||||
|
||||
void voice_heartbeat_task(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
while (true) {
|
||||
bool active = false;
|
||||
bool connected = false;
|
||||
bool started = false;
|
||||
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
active = s_voice.session_active && !s_voice.stop_requested;
|
||||
connected = s_voice.ws_connected;
|
||||
started = s_voice.started;
|
||||
voice_unlock();
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (connected && started) {
|
||||
ESP_LOGI(TAG, "[stage] heartbeat_send");
|
||||
(void)voice_send_directive("continue-task", "HeartBeat", true);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(CONFIG_TQ_VOICE_HEARTBEAT_SEC * 1000));
|
||||
}
|
||||
|
||||
bool delete_with_caps = false;
|
||||
if (voice_lock(VOICE_STATUS_LOCK_TIMEOUT_MS)) {
|
||||
delete_with_caps = s_voice.heartbeat_task_with_caps;
|
||||
s_voice.heartbeat_task = NULL;
|
||||
s_voice.heartbeat_task_with_caps = false;
|
||||
voice_unlock();
|
||||
}
|
||||
voice_delete_self_task(delete_with_caps);
|
||||
}
|
||||
Reference in New Issue
Block a user