141 lines
4.8 KiB
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);
|
|
}
|