Files
AI_Printer/components/domain/src/voice_interaction_tasks.c

141 lines
4.8 KiB
C

#include "voice_interaction_internal.h"
#include <string.h>
#include "esp_audio_enc.h"
void voice_uplink_task(void *arg) {
(void)arg;
while (true) {
bool active = false;
bool connected = false;
bool started = false;
bool tap_active = false;
bool speech_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;
speech_active = s_voice.speech_active;
listening = (s_voice.dialog_state == VOICE_DIALOG_STATE_LISTENING);
voice_unlock();
}
if (!active) {
break;
}
if (!(connected && started && listening && tap_active && speech_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.speech_active = false;
s_voice.dialog_state = VOICE_DIALOG_STATE_IDLE;
s_voice.last_event_ms = voice_now_ms();
}
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) {
(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);
}