254 lines
6.4 KiB
C
254 lines
6.4 KiB
C
#include "ai_interaction/ai_interaction.h"
|
|
#include "ai_interaction/ai_audio.h"
|
|
#include "ai_interaction/ai_text.h"
|
|
/* #include "smartbox_rcsp_manage.h" */
|
|
#include "btstack/avctp_user.h"
|
|
#include "app_task.h"
|
|
#include "bt.h"
|
|
#include "ui/ui_api.h"
|
|
#include "string.h"
|
|
#if TCFG_AI_INTERACTION_ENABLE
|
|
volatile u8 *tts_txt = NULL;
|
|
volatile u8 *ai_txt1 = NULL;
|
|
volatile u8 *ai_dial_txt1 = NULL;
|
|
volatile u8 *ai_txt2 = NULL;
|
|
volatile u8 *ai_txttempa = NULL;
|
|
volatile u8 *ai_txttempb = NULL;
|
|
u8 aidial_flag;
|
|
#define AI_INTERACTION_REC_LIMIT_MIN_MS (1000) //录音时间最低限制
|
|
#define MAX_TXT_NUM (500) //最大显示的字数
|
|
//截取UTF8编码第num位到末尾字符串
|
|
static char *getutf8stringendstring(u8 *str, int num)
|
|
{
|
|
char *substring = NULL;
|
|
free(substring);
|
|
int length = strlen((char *)str);
|
|
int i = 0;
|
|
const char *starstr = (char *)str;
|
|
while (*starstr != '\0' && i < num) {
|
|
if ((*starstr & 0XC0) != 0X80) {
|
|
i++;
|
|
}
|
|
starstr++;
|
|
}
|
|
substring = strdup(starstr);
|
|
return substring;
|
|
}
|
|
//截取UTF8编码后num位字符
|
|
static char *getutf8stringend(u8 *str, int num)
|
|
{
|
|
int length = strlen((char *)str);
|
|
int i = length - 1;
|
|
int count = 0;
|
|
while (i >= 0 && count < num) {
|
|
if ((str[i] & 0XC0) != 0X80) {
|
|
count++;
|
|
}
|
|
i--;
|
|
}
|
|
int substringlength = length - i - 1;
|
|
char *substring = malloc(substringlength + 1);
|
|
strncpy(substring, (char *)&str[i + 1], substringlength);
|
|
substring[substringlength] = '\0';
|
|
return substring;
|
|
}
|
|
//截取UTF8字符串开始到指定位置
|
|
static u8 *getutf8stringfrontstring(u8 *str, int num)
|
|
{
|
|
char *substring = NULL;
|
|
free(substring);
|
|
int i = 0;
|
|
const u8 *starstr = str;
|
|
while (*starstr != '\0' && i < num) {
|
|
if ((*starstr & 0XC0) != 0X80) {
|
|
i++;
|
|
}
|
|
starstr++;
|
|
}
|
|
int substringlength = starstr - str + 1;
|
|
substring = malloc(substringlength + 1);
|
|
strncpy(substring, (char *)str, substringlength);
|
|
substring[substringlength] = '\0';
|
|
return (u8 *)substring;
|
|
}
|
|
|
|
struct _AI_INTERACTION {
|
|
u8 rec_busy;
|
|
u8 err;
|
|
u32 lose_cnt;
|
|
u32 rec_min_time;
|
|
};
|
|
static struct _AI_INTERACTION ai_interaction;
|
|
|
|
|
|
static void ai_audio_evt_cb(int event)
|
|
{
|
|
switch (event) {
|
|
case AI_AUDIO_EVENT_ERR_REC_START:
|
|
ai_interaction.err = 1;
|
|
break;
|
|
case AI_AUDIO_EVENT_ERR_REC_DATA:
|
|
if (ai_interaction.lose_cnt < (u32) - 1) {
|
|
ai_interaction.lose_cnt ++;
|
|
}
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
static int ai_text_rx_cb(u8 ai_text, u8 *data, int len)
|
|
{
|
|
aidial_flag = ai_text;
|
|
printf("aidial_flag_txt:%d\n", aidial_flag);
|
|
if (ai_dial_txt1) {
|
|
free((void *)ai_dial_txt1);
|
|
ai_dial_txt1 = NULL;
|
|
}
|
|
ai_dial_txt1 = data;
|
|
ai_dial_txt1 = malloc(len + 1);
|
|
memset((void *)ai_dial_txt1, '\0', len + 1);
|
|
memcpy((void *)ai_dial_txt1, data, len);
|
|
ai_dial_txt1[len] = '\0';
|
|
u8 *str = getutf8stringfrontstring(data, MAX_TXT_NUM + 1);
|
|
char *str1 = getutf8stringendstring(data, MAX_TXT_NUM);
|
|
if (ai_text && data != NULL) {//1----ai文本
|
|
if (len < strlen((char *)str)) {
|
|
str[len] = '\0';
|
|
}
|
|
tts_txt = str;
|
|
if (len > 430) {
|
|
free((void *)ai_txt2);
|
|
ai_txt2 = (u8 *)strdup(str1);
|
|
} else {
|
|
ai_txt2 = NULL;
|
|
}
|
|
}
|
|
if (!ai_text) {
|
|
free((void *)ai_txt1);
|
|
ai_txt1 = data;
|
|
ai_txt1 = malloc(len + 1);
|
|
memset((void *)ai_txt1, '\0', len + 1);
|
|
memcpy((void *)ai_txt1, data, len);
|
|
ai_txt1[len] = '\0';
|
|
}
|
|
if (ai_text == 2) {
|
|
UI_MSG_POST("AI_ERROR");
|
|
}
|
|
// UTF8
|
|
ai_txttempa = tts_txt;
|
|
ai_txttempb = ai_txt2;
|
|
if (ai_text) {
|
|
UI_MSG_POST("SEND_TXT");
|
|
}
|
|
log_i("rx text:%d, %s \n", ai_text, data);
|
|
put_buf(data, len);
|
|
return false;
|
|
}
|
|
|
|
void ai_interaction_release(void)
|
|
{
|
|
ai_audio_stop(1);
|
|
ai_text_release();
|
|
memset(&ai_interaction, 0, sizeof(struct _AI_INTERACTION));
|
|
}
|
|
|
|
|
|
int ai_interaction_rec_stop(void)
|
|
{
|
|
if (!ai_interaction.rec_busy) {
|
|
log_e("rec no run \n");
|
|
return false;
|
|
}
|
|
ai_interaction.rec_busy = 0;
|
|
|
|
u8 cur_task = app_get_curr_task();
|
|
if (APP_BT_TASK != cur_task) {
|
|
// 为啥不是蓝牙模式?
|
|
log_e("cur task:%d no support ai rec stop \n", cur_task);
|
|
/* ai_interaction_release(); */
|
|
ai_audio_stop(1);
|
|
return false;
|
|
}
|
|
if (!time_after(jiffies, ai_interaction.rec_min_time)) {
|
|
log_e("limit time:%d,%d \n", jiffies, ai_interaction.rec_min_time);
|
|
ai_audio_stop(1);
|
|
return false;
|
|
} else if (ai_interaction.err) {
|
|
log_e("rec err \n");
|
|
ai_audio_stop(1);
|
|
return false;
|
|
} else {
|
|
log_i("stop lose:%d \n", ai_interaction.lose_cnt);
|
|
ai_audio_stop(0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int ai_interaction_rec_start(void)
|
|
{
|
|
extern u8 get_rcsp_connect_status(void);
|
|
if (!get_rcsp_connect_status()) {
|
|
log_e("rcsp disconnect \n");
|
|
return false;
|
|
}
|
|
|
|
u8 cur_task = app_get_curr_task();
|
|
switch (cur_task) {
|
|
case APP_POWERON_TASK:
|
|
case APP_WATCH_UPDATE_TASK:
|
|
case APP_SMARTBOX_ACTION_TASK:
|
|
// 这些模式不支持跳转到录音
|
|
log_e("cur task:%d no support ai rec start \n", cur_task);
|
|
return false;
|
|
/* break; */
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* if (bt_must_work()) { */
|
|
/* log_e("bt busy \n"); */
|
|
/* return false; */
|
|
/* } */
|
|
|
|
// 跳转到蓝牙模式
|
|
app_task_switch_to(APP_BT_TASK, 0);
|
|
|
|
if (bt_a2dp_get_status() == BT_MUSIC_STATUS_STARTING) {
|
|
log_i("switch a2dp \n");
|
|
bt_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL);
|
|
}
|
|
|
|
// 释放旧的
|
|
ai_interaction_release();
|
|
|
|
// 状态初始化
|
|
ai_interaction.rec_min_time = jiffies + msecs_to_jiffies(AI_INTERACTION_REC_LIMIT_MIN_MS);
|
|
ai_interaction.rec_busy = 1;
|
|
|
|
// 启动录音
|
|
int ret = ai_audio_start();
|
|
if (ret == false) {
|
|
ai_interaction.rec_busy = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ai_interaction_init(void)
|
|
{
|
|
memset(&ai_interaction, 0, sizeof(struct _AI_INTERACTION));
|
|
ai_audio_init(ai_audio_evt_cb);
|
|
ai_text_init(ai_text_rx_cb);
|
|
}
|
|
|
|
static u8 ai_interaction_idle_query(void)
|
|
{
|
|
return !ai_interaction.rec_busy;
|
|
}
|
|
REGISTER_LP_TARGET(ai_lp_target) = {
|
|
.name = "ai",
|
|
.is_idle = ai_interaction_idle_query,
|
|
};
|
|
|
|
#endif
|
|
|