#pragma once #include #include #include #include "esp_opus_dec.h" #include "esp_opus_enc.h" #include "esp_websocket_client.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/task.h" #include "voice_interaction.h" #define VOICE_STREAMING_MODE "duplex" #define VOICE_TASK_GROUP "aigc" #define VOICE_TASK_NAME "multimodal-generation" #define VOICE_FUNCTION_NAME "generation" #define VOICE_MODEL_NAME "multimodal-dialog" #define VOICE_SAMPLE_BYTES 2 #define VOICE_STATUS_LOCK_TIMEOUT_MS 1000 #define VOICE_WS_SEND_TIMEOUT_MS 1000 #define VOICE_WS_TASK_STACK 24576 #define VOICE_UPLINK_TASK_STACK 32768 #define VOICE_HEARTBEAT_TASK_STACK 4096 #define VOICE_START_CONNECT_TIMEOUT_MS 8000 #define VOICE_AUDIO_IO_TIMEOUT_MS 1200 #define VOICE_AUDIO_DRAIN_MARGIN_MS 120 #define VOICE_AUDIO_DRAIN_QUIET_MS 180 #define VOICE_AUDIO_DRAIN_WAIT_MS 2200 #define VOICE_AUDIO_DRAIN_WAIT_ON_STOP_MS 3500 typedef struct { SemaphoreHandle_t lock; esp_websocket_client_handle_t ws; TaskHandle_t uplink_task; TaskHandle_t heartbeat_task; bool uplink_task_with_caps; bool heartbeat_task_with_caps; void *opus_enc; void *opus_dec; int opus_enc_in_size; int opus_enc_out_size; uint8_t *opus_tx_buf; int16_t *pcm_tx_buf; uint8_t *pcm_rx_buf; size_t pcm_rx_buf_size; uint8_t *text_agg; size_t text_agg_size; uint8_t *bin_agg; size_t bin_agg_size; bool ready; bool session_active; bool ws_connected; bool started; bool tap_active; bool stop_requested; bool ws_low_stack_warned; bool response_first_sentence_checked; voice_dialog_state_t dialog_state; char task_id[40]; char dialog_id[40]; char device_uuid[40]; char last_error[128]; int64_t last_event_ms; int64_t last_downstream_ms; int64_t playback_deadline_ms; uint32_t upstream_packets; uint32_t downstream_packets; } voice_context_t; extern voice_context_t s_voice; int64_t voice_now_ms(void); void voice_fill_err(char *err, size_t err_len, const char *msg); void voice_set_last_error_locked(const char *msg); bool voice_lock(uint32_t timeout_ms); void voice_unlock(void); void voice_log_status_snapshot(const char *stage); void voice_log_heap_snapshot(const char *stage); void voice_wait_audio_playback_done(uint32_t timeout_ms, const char *stage); void voice_close_audio_with_drain(uint32_t timeout_ms, const char *stage); void *voice_malloc_prefer_psram(size_t size); void *voice_calloc_prefer_psram(size_t n, size_t size); void *voice_realloc_prefer_psram(void *ptr, size_t size); BaseType_t voice_create_task_prefer_psram(TaskFunction_t task_fn, const char *name, uint32_t stack_size, UBaseType_t priority, TaskHandle_t *out_task, bool *out_with_caps); void voice_delete_task(TaskHandle_t task, bool with_caps); void voice_delete_self_task(bool with_caps); void voice_make_uuid(char out[40]); void voice_make_device_uuid(char out[40]); const char *voice_safe_user_id(void); esp_err_t voice_setup_opus(char *err, size_t err_len); esp_err_t voice_open_audio_for_dialog(char *err, size_t err_len); void voice_release_runtime_resources(void); esp_err_t voice_send_directive(const char *action, const char *directive, bool with_dialog_id); void voice_websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data); void voice_interaction_ws_init_cjson_hooks(void); void voice_uplink_task(void *arg); void voice_heartbeat_task(void *arg);