715 lines
22 KiB
C
715 lines
22 KiB
C
#include "app_config.h"
|
||
#include "server/audio_server.h"
|
||
#include "server/server_core.h"
|
||
#include "generic/circular_buf.h"
|
||
#include "os/os_api.h"
|
||
#include "os/os_api.h"
|
||
#include "app_config.h"
|
||
#include <time.h>
|
||
#include "event/key_event.h"
|
||
#include "asr.h"
|
||
#include "ivPolos.h"
|
||
#include "fig_asr_api.h"
|
||
#include "fig_asr_type.h"
|
||
|
||
|
||
#if (defined CONFIG_ASR_ALGORITHM) && (CONFIG_ASR_ALGORITHM == ROOBO_ALGORITHM)
|
||
|
||
#include "resmapping_table.h"
|
||
|
||
#define ROOBO_DUAL_MIC_ALGORITHM 0 //选择单mic/双mic算法
|
||
|
||
/*每次AEC输入的数据量大小, 匹配的每个大小是short*/
|
||
#define ROOBO_AEC_INPUT_SHORT_LEN 512
|
||
#define ROOBO_ASR_INPUT_SHORT_LEN 160 /* 10ms */
|
||
//#define ROOBO_ASR_INPUT_SHORT_LEN 480 /* 30ms */
|
||
|
||
#define CACHE_BUF_SIZE (32 * 1024)
|
||
|
||
typedef struct {
|
||
int wordId;
|
||
void *text;
|
||
float score;
|
||
} roobo_asr_result_t;
|
||
|
||
typedef struct {
|
||
short *left_mic; /* 16bit第一路麦克风 */
|
||
short *right_mic; /* 16bit第二路麦克风,没有填NULL */
|
||
short *left_aec; /* 16bit第一路参考信号 */
|
||
short *right_aec; /* 16bit第二路参考信号, 没有填NULL */
|
||
int len; /* 对应short类型长度, 必须= 512*sizeof(short) */
|
||
} roobo_aec_stream_t;
|
||
|
||
static struct {
|
||
FIG_INST pFigAsr;
|
||
char fig_aec_buf[300 * 1024];
|
||
u16 volatile run_flag;
|
||
u16 sample_rate;
|
||
struct server *mic_enc;
|
||
struct server *linein_enc;
|
||
cbuffer_t mic_cbuf;
|
||
cbuffer_t asr_cbuf;
|
||
cbuffer_t aec_cbuf;
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
cbuffer_t linein_cbuf;
|
||
char linein_buf[CACHE_BUF_SIZE];
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
char mic_buf[CACHE_BUF_SIZE * 2];
|
||
#else
|
||
char mic_buf[CACHE_BUF_SIZE];
|
||
#endif
|
||
|
||
#else
|
||
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
char mic_buf[CACHE_BUF_SIZE * 3];
|
||
#else
|
||
char mic_buf[CACHE_BUF_SIZE * 2];
|
||
#endif
|
||
|
||
#endif
|
||
char asr_buf[CACHE_BUF_SIZE];
|
||
char aec_buf[CACHE_BUF_SIZE];
|
||
OS_SEM sem;
|
||
OS_SEM asr_sem;
|
||
OS_SEM aec_sem;
|
||
} roobo_server;
|
||
#define __this (&roobo_server)
|
||
|
||
static int wtk_handler(const char *str_keyword)
|
||
{
|
||
struct key_event evt = {0};
|
||
|
||
char time_str[128] = {0};
|
||
struct tm timeinfo = {0};
|
||
time_t timestamp = time(NULL) + 28800;
|
||
localtime_r(×tamp, &timeinfo);
|
||
strftime(time_str, sizeof(time_str), "%Y-%m-%dT%H:%M:%S", &timeinfo);
|
||
printf("{ wakeup_word: \"小爱小爱\", awaken_time: %s}\n", time_str);;
|
||
|
||
static const char xiao_ai_xiao_ai[] = {0xd0, 0xa1, 0xb0, 0xac, 0xd0, 0xa1, 0xb0, 0xac}; //小艾小艾
|
||
static const char bo_fang_yin_yue[] = {0xb2, 0xa5, 0xb7, 0xc5, 0xd2, 0xf4, 0xc0, 0xd6 };// 播放音乐
|
||
static const char zan_ting_yin_yue[] = {0xd4, 0xdd, 0xcd, 0xa3, 0xd2, 0xf4, 0xc0, 0xd6}; // 暂停音乐
|
||
static const char zeng_da_yin_liang[] = {0xd4, 0xf6, 0xb4, 0xf3, 0xd2, 0xf4, 0xc1, 0xbf}; //增大音量
|
||
static const char jian_xiao_yin_liang[] = {0xbc, 0xf5, 0xd0, 0xa1, 0xd2, 0xf4, 0xc1, 0xbf}; //减小音量
|
||
static const char shang_yi_qu[] = {0xc9, 0xcf, 0xd2, 0xbb, 0xc7, 0xfa}; //上一曲
|
||
static const char xia_yi_qu[] = {0xcf, 0xc2, 0xd2, 0xbb, 0xc7, 0xfa}; //下一曲
|
||
|
||
evt.type = KEY_EVENT_USER;
|
||
|
||
if (!memcmp(str_keyword, zan_ting_yin_yue, sizeof(zan_ting_yin_yue))) {
|
||
evt.action = KEY_EVENT_HOLD;
|
||
evt.value = KEY_LOCAL;
|
||
} else if (!memcmp(str_keyword, bo_fang_yin_yue, sizeof(bo_fang_yin_yue))) {
|
||
evt.action = KEY_EVENT_UP;
|
||
evt.value = KEY_LOCAL;
|
||
} else if (!memcmp(str_keyword, shang_yi_qu, sizeof(shang_yi_qu))) {
|
||
evt.action = KEY_EVENT_LONG;
|
||
evt.value = KEY_UP;
|
||
} else if (!memcmp(str_keyword, xia_yi_qu, sizeof(xia_yi_qu))) {
|
||
evt.action = KEY_EVENT_LONG;
|
||
evt.value = KEY_DOWN;
|
||
} else if (!memcmp(str_keyword, zeng_da_yin_liang, sizeof(zeng_da_yin_liang))) {
|
||
evt.action = KEY_EVENT_CLICK;
|
||
evt.value = KEY_DOWN;
|
||
} else if (!memcmp(str_keyword, jian_xiao_yin_liang, sizeof(jian_xiao_yin_liang))) {
|
||
evt.action = KEY_EVENT_CLICK;
|
||
evt.value = KEY_UP;
|
||
} else {
|
||
evt.action = KEY_EVENT_CLICK;
|
||
evt.value = KEY_ENC;
|
||
}
|
||
|
||
key_event_notify(KEY_EVENT_FROM_USER, &evt);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 函数名称: roobo_aec_process
|
||
* 函数功能: roobo aec 处理
|
||
* 输入参数:roobo_aec_stream_t input_stream 输入的audio数据信息, 16K 16bit音频,每个音频的长度为ROOBO_AEC_INPUT_SHORT_LEN*sizeof(short)
|
||
* 输入参数: void* output_data 输出音频的16K 16bit输出音频 512 * sizeof(short)
|
||
* 输出参数: int* out_size 输出音频长度, 12 * sizeof(short)
|
||
* 返回值: int 0 成功,非0 失败
|
||
*/
|
||
static int roobo_aec_process(roobo_aec_stream_t input_st, void *output_data, int *out_size)
|
||
{
|
||
short input_data[ROOBO_AEC_INPUT_SHORT_LEN * 4] = {0};
|
||
|
||
if (input_st.len != ROOBO_AEC_INPUT_SHORT_LEN) {
|
||
printf("input data len(short) %d != required %d\n", input_st.len, ROOBO_AEC_INPUT_SHORT_LEN);
|
||
return -1;
|
||
} else if (!input_st.left_mic || !input_st.left_aec) {
|
||
printf("input mic or aec buf is NULL, reject\n");
|
||
return -2;
|
||
}
|
||
|
||
short *left_mic = input_st.left_mic;
|
||
short *left_aec = input_st.left_aec;
|
||
short *right_mic = input_st.right_mic;
|
||
short *right_aec = input_st.right_aec;
|
||
|
||
if (right_mic) {
|
||
if (right_aec) {
|
||
for (int i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; i++) {
|
||
input_data[4 * i] = *left_mic++;
|
||
input_data[4 * i + 1] = *right_mic++;
|
||
input_data[4 * i + 2] = *left_aec++;
|
||
input_data[4 * i + 3] = *right_aec++;
|
||
}
|
||
} else {
|
||
for (int i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; i++) {
|
||
input_data[4 * i] = *left_mic++;
|
||
input_data[4 * i + 1] = *right_mic++;
|
||
input_data[4 * i + 2] = *left_aec++;
|
||
// input_data[4 * i + 3] = *left_aec++;
|
||
}
|
||
}
|
||
} else {
|
||
for (int i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; i++) {
|
||
input_data[4 * i] = *left_mic++;
|
||
input_data[4 * i + 2] = *left_aec++;
|
||
}
|
||
}
|
||
|
||
int ret = POLOS_AUDIOWRITE(input_data, sizeof(input_data), output_data, out_size);
|
||
|
||
#ifdef WIFI_PCM_STREAN_SOCKET_ENABLE
|
||
s16 *output = (s16 *)output_data;
|
||
for (int i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; i++) {
|
||
input_data[4 * i + 3] = *output++; //left_mic right_mic left_linein aec
|
||
}
|
||
extern void wifi_pcm_stream_socket_send(u8 * buf, u32 len);
|
||
wifi_pcm_stream_socket_send((u8 *)input_data, sizeof(input_data));
|
||
#endif
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
* 函数名称: roobo_aec_init
|
||
* 函数功能: roobo aec 初始化
|
||
* 输入参数: aec sdk内部使用的内存大小
|
||
* 输出参数: void
|
||
* 返回值: int 0 成功,非0 失败
|
||
*/
|
||
static int roobo_aec_init(void *mem, void *userdata)
|
||
{
|
||
printf("aec version = %d\n", GetAECVersion());
|
||
return POLOS_INIT(mem);
|
||
}
|
||
|
||
static int roobo_asr_process(short *buf, int len, char *text, float *score)
|
||
{
|
||
// static int process_index = 0;
|
||
// if(++process_index % 10 == 0) {
|
||
// printf("[%d]figasr_process %d", process_index, len);
|
||
// }
|
||
|
||
bool bAudioEnd = 0;
|
||
PAsrResult pResult = NULL;
|
||
int ret = FigWriteAudio(__this->pFigAsr, (char *)buf, len * sizeof(short), bAudioEnd, &pResult);
|
||
if (ret != 0) {
|
||
printf("Error: write audio fail with error code = %d\n", ret);
|
||
return ret;
|
||
}
|
||
|
||
// process result
|
||
if (pResult != NULL) {
|
||
printf("asr result:word %d: [%lu] %s!!!!\n", pResult->nWordId, strlen(pResult->szText), pResult->szText);
|
||
printf("asr score %d, form %d to %d", pResult->nCmScore, pResult->nBegin, pResult->nEnd);
|
||
sprintf(text, "%s", pResult->szText);
|
||
*score = pResult->nWordId;
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int roobo_asr_init(void *userdata)
|
||
{
|
||
int ret = 0;
|
||
|
||
ret = FigCreateInst(&__this->pFigAsr, (const char *)nnet, (const char *)graph_cmd);
|
||
if (ret != 0) {
|
||
printf("Error: FigCreateInst fail with error code = %d\n", ret);
|
||
goto exit;
|
||
}
|
||
|
||
ret = FigStartProcess(__this->pFigAsr);
|
||
if (ret != 0) {
|
||
printf("Error: asr start fail with error code = %d\n", ret);
|
||
goto exit;
|
||
}
|
||
/* printf("roobo_asr_init ok,,,0x%x,0x%x\n", nnet, graph_cmd); */
|
||
|
||
exit:
|
||
return ret;
|
||
}
|
||
|
||
static int roobo_asr_deinit(void)
|
||
{
|
||
int ret = FigStopProcess(__this->pFigAsr);
|
||
if (ret != 0) {
|
||
printf("Error: asr stop fail with error code = %d\n", ret);
|
||
return ret;
|
||
}
|
||
|
||
ret = FigDestroyInst(__this->pFigAsr);
|
||
if (ret != 0) {
|
||
printf("Error: uninitialize fail with error code = %d\n", ret);
|
||
return ret;
|
||
}
|
||
__this->pFigAsr = NULL;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void roobo_asr_reset(void)
|
||
{
|
||
asr_reset();
|
||
}
|
||
|
||
static int roobo_vfs_fwrite(void *file, void *data, u32 len)
|
||
{
|
||
cbuffer_t *cbuf = (cbuffer_t *)file;
|
||
u32 wlen;
|
||
|
||
wlen = cbuf_write(cbuf, data, len);
|
||
if (wlen != len) {
|
||
cbuf_clear(&__this->mic_cbuf);
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
cbuf_clear(&__this->linein_cbuf);
|
||
#endif
|
||
puts("aec busy!\n");
|
||
}
|
||
|
||
if (file == (void *)&__this->mic_cbuf) {
|
||
os_sem_set(&__this->sem, 0);
|
||
os_sem_post(&__this->sem);
|
||
}
|
||
return len;
|
||
}
|
||
|
||
static int roobo_vfs_fclose(void *file)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
//录音文件操作方法集。传递给MIC底层驱动调用
|
||
static const struct audio_vfs_ops roobo_vfs_ops = {
|
||
.fwrite = roobo_vfs_fwrite,
|
||
.fclose = roobo_vfs_fclose,
|
||
};
|
||
|
||
|
||
//功能:底层驱动回调函数
|
||
static void enc_server_event_handler(void *priv, int argc, int *argv)
|
||
{
|
||
switch (argv[0]) {
|
||
case AUDIO_SERVER_EVENT_ERR:
|
||
case AUDIO_SERVER_EVENT_END:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static int mic_record_start(int sample_rate)
|
||
{
|
||
int err = -1;
|
||
union audio_req req = {0};
|
||
|
||
//打开enc_server
|
||
if (!__this->mic_enc) {
|
||
__this->mic_enc = server_open("audio_server", "enc");
|
||
if (!__this->mic_enc) {
|
||
goto _mic_err_;
|
||
}
|
||
server_register_event_handler(__this->mic_enc, NULL, enc_server_event_handler);
|
||
}
|
||
|
||
//初始化cycle_buf
|
||
cbuf_init(&__this->mic_cbuf, __this->mic_buf, sizeof(__this->mic_buf));
|
||
|
||
//MIC数据采集配置
|
||
req.enc.cmd = AUDIO_ENC_OPEN; //命令
|
||
req.enc.volume = CONFIG_AISP_MIC_ADC_GAIN; //录音音量
|
||
req.enc.output_buf = NULL; //缓存buf
|
||
req.enc.sample_rate = sample_rate; //采样率
|
||
req.enc.format = "pcm"; //录音数据格式
|
||
#ifdef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
req.enc.channel = 3;
|
||
req.enc.channel_bit_map = BIT(CONFIG_AISP_MIC0_ADC_CHANNEL) | BIT(CONFIG_AISP_MIC1_ADC_CHANNEL) | BIT(CONFIG_AISP_LINEIN_ADC_CHANNEL);
|
||
#else
|
||
req.enc.channel = 2;
|
||
req.enc.channel_bit_map = BIT(CONFIG_AISP_MIC0_ADC_CHANNEL) | BIT(CONFIG_AISP_LINEIN_ADC_CHANNEL);
|
||
#endif // ROOBO_DUAL_MIC_ALGORITHM
|
||
#else
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
req.enc.channel = 2; //采样通道数目
|
||
req.enc.channel_bit_map = BIT(CONFIG_AISP_MIC0_ADC_CHANNEL) | BIT(CONFIG_AISP_MIC1_ADC_CHANNEL);
|
||
#else
|
||
req.enc.channel = 1; //采样通道数目
|
||
req.enc.channel_bit_map = BIT(CONFIG_AISP_MIC0_ADC_CHANNEL);
|
||
#endif // ROOBO_DUAL_MIC_ALGORITHM
|
||
#endif
|
||
req.enc.frame_size = ROOBO_AEC_INPUT_SHORT_LEN * 2 * req.enc.channel; //数据帧大小
|
||
req.enc.output_buf_len = req.enc.frame_size * 3; //缓存buf大小
|
||
req.enc.sample_source = "mic"; //采样源
|
||
req.enc.vfs_ops = &roobo_vfs_ops; //文件操作方法集
|
||
req.enc.msec = 0; //采样时间
|
||
req.enc.file = (FILE *)&__this->mic_cbuf;
|
||
|
||
//发送录音请求
|
||
err = server_request(__this->mic_enc, AUDIO_REQ_ENC, &req);
|
||
if (err) {
|
||
goto _mic_err_;
|
||
}
|
||
|
||
#ifdef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
extern void adc_multiplex_set_gain(const char *source, u8 channel_bit_map, u8 gain);
|
||
adc_multiplex_set_gain("mic", BIT(CONFIG_AISP_LINEIN_ADC_CHANNEL), CONFIG_AISP_LINEIN_ADC_GAIN);
|
||
#endif
|
||
|
||
return 0;
|
||
|
||
_mic_err_:
|
||
if (__this->mic_enc) {
|
||
server_close(__this->mic_enc);
|
||
__this->mic_enc = NULL;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
static int linein_record_start(int sample_rate)
|
||
{
|
||
int err = -1;
|
||
union audio_req req = {0};
|
||
|
||
//打开enc_server
|
||
if (!__this->linein_enc) {
|
||
__this->linein_enc = server_open("audio_server", "enc");
|
||
if (!__this->linein_enc) {
|
||
goto _mic_err_;
|
||
}
|
||
server_register_event_handler(__this->linein_enc, NULL, enc_server_event_handler);
|
||
}
|
||
|
||
//初始化cycle_buf
|
||
cbuf_init(&__this->linein_cbuf, __this->linein_buf, sizeof(__this->linein_buf));
|
||
|
||
//MIC数据采集配置
|
||
req.enc.cmd = AUDIO_ENC_OPEN; //命令
|
||
req.enc.channel = 1; //采样通道数目
|
||
req.enc.volume = CONFIG_AISP_LINEIN_ADC_GAIN; //录音音量
|
||
req.enc.output_buf = NULL; //缓存buf
|
||
req.enc.sample_rate = sample_rate; //采样率
|
||
req.enc.format = "pcm"; //录音数据格式
|
||
req.enc.frame_size = ROOBO_AEC_INPUT_SHORT_LEN * 2; //数据帧大小
|
||
req.enc.output_buf_len = req.enc.frame_size * 3; //缓存buf大小
|
||
req.enc.sample_source = "linein"; //采样源
|
||
req.enc.vfs_ops = &roobo_vfs_ops; //文件操作方法集
|
||
req.enc.msec = 0; //采样时间
|
||
req.enc.file = (FILE *)&__this->linein_cbuf;
|
||
req.enc.channel_bit_map = BIT(CONFIG_AISP_LINEIN_ADC_CHANNEL);
|
||
|
||
//发送录音请求
|
||
err = server_request(__this->linein_enc, AUDIO_REQ_ENC, &req);
|
||
if (err) {
|
||
goto _mic_err_;
|
||
}
|
||
|
||
return 0;
|
||
|
||
_mic_err_:
|
||
printf("linin_start failed\n");
|
||
|
||
if (__this->linein_enc) {
|
||
server_close(__this->linein_enc);
|
||
__this->linein_enc = NULL;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
#endif
|
||
|
||
static void roobo_audiolib_handler(short *left_mic_buf, short *right_mic_buf, short *left_linein_buf, short *right_linein_buf, int len)
|
||
{
|
||
int wlen;
|
||
short aec_out_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
int out_len = 0;
|
||
|
||
roobo_aec_stream_t input_stream = {
|
||
.left_mic = left_mic_buf,
|
||
.right_mic = right_mic_buf,
|
||
.left_aec = left_linein_buf,
|
||
.right_aec = right_linein_buf,
|
||
.len = len,
|
||
};
|
||
|
||
roobo_aec_process(input_stream, aec_out_buf, &out_len);
|
||
out_len *= sizeof(short);
|
||
wlen = cbuf_write(&__this->asr_cbuf, aec_out_buf, out_len);
|
||
if (wlen != out_len) {
|
||
cbuf_clear(&__this->asr_cbuf);
|
||
puts("asr busy!\n");
|
||
}
|
||
os_sem_set(&__this->asr_sem, 0);
|
||
os_sem_post(&__this->asr_sem);
|
||
|
||
wlen = cbuf_write(&__this->aec_cbuf, aec_out_buf, out_len);
|
||
if (wlen != out_len) {
|
||
/* cbuf_clear(&__this->aec_cbuf); */
|
||
/* puts("ai busy!\n"); */
|
||
}
|
||
os_sem_set(&__this->aec_sem, 0);
|
||
os_sem_post(&__this->aec_sem);
|
||
}
|
||
|
||
static void roobo_aec_handler(void *priv)
|
||
{
|
||
for (;;) {
|
||
os_sem_pend(&__this->sem, 0);
|
||
|
||
#ifdef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
short temp_buf[ROOBO_AEC_INPUT_SHORT_LEN * 3];
|
||
short left_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short right_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short left_linein_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
while ((cbuf_get_data_size(&__this->mic_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 6)) {
|
||
if (0 == cbuf_read(&__this->mic_cbuf, (void *)temp_buf, sizeof(temp_buf))) {
|
||
break;
|
||
}
|
||
for (u32 i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; ++i) {
|
||
left_mic_buf[i] = temp_buf[3 * i] ;
|
||
right_mic_buf[i] = temp_buf[3 * i + 1] ;
|
||
left_linein_buf[i] = temp_buf[3 * i + 2];
|
||
}
|
||
roobo_audiolib_handler(left_mic_buf, right_mic_buf, left_linein_buf, NULL, ROOBO_AEC_INPUT_SHORT_LEN);
|
||
}
|
||
#else
|
||
short temp_buf[ROOBO_AEC_INPUT_SHORT_LEN * 2];
|
||
short left_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short left_linein_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
while ((cbuf_get_data_size(&__this->mic_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 4)) {
|
||
if (0 == cbuf_read(&__this->mic_cbuf, (void *)temp_buf, sizeof(temp_buf))) {
|
||
break;
|
||
}
|
||
for (u32 i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; ++i) {
|
||
left_mic_buf[i] = temp_buf[2 * i] ;
|
||
left_linein_buf[i] = temp_buf[2 * i + 1];
|
||
}
|
||
roobo_audiolib_handler(left_mic_buf, NULL, left_linein_buf, NULL, ROOBO_AEC_INPUT_SHORT_LEN);
|
||
}
|
||
#endif // ROOBO_DUAL_MIC_ALGORITHM
|
||
|
||
#else
|
||
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
short temp_buf[ROOBO_AEC_INPUT_SHORT_LEN * 2];
|
||
short left_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short right_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short left_linein_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
while ((cbuf_get_data_size(&__this->mic_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 4) && (cbuf_get_data_size(&__this->linein_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 2)) {
|
||
if (0 == cbuf_read(&__this->mic_cbuf, (void *)temp_buf, sizeof(temp_buf))) {
|
||
break;
|
||
}
|
||
if (0 == cbuf_read(&__this->linein_cbuf, (void *)left_linein_buf, sizeof(left_linein_buf))) {
|
||
break;
|
||
}
|
||
|
||
for (u32 i = 0; i < ROOBO_AEC_INPUT_SHORT_LEN; ++i) {
|
||
left_mic_buf[i] = temp_buf[2 * i] ;
|
||
right_mic_buf[i] = temp_buf[2 * i + 1];
|
||
}
|
||
roobo_audiolib_handler(left_mic_buf, right_mic_buf, left_linein_buf, NULL, ROOBO_AEC_INPUT_SHORT_LEN);
|
||
}
|
||
#else
|
||
short left_mic_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
short left_linein_buf[ROOBO_AEC_INPUT_SHORT_LEN];
|
||
while ((cbuf_get_data_size(&__this->mic_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 2)
|
||
&& (cbuf_get_data_size(&__this->linein_cbuf) >= ROOBO_AEC_INPUT_SHORT_LEN * 2)) {
|
||
if (0 == cbuf_read(&__this->mic_cbuf, (void *)left_mic_buf, sizeof(left_mic_buf))) {
|
||
break;
|
||
}
|
||
if (0 == cbuf_read(&__this->linein_cbuf, (void *)left_linein_buf, sizeof(left_linein_buf))) {
|
||
break;
|
||
}
|
||
roobo_audiolib_handler(left_mic_buf, NULL, left_linein_buf, NULL, ROOBO_AEC_INPUT_SHORT_LEN);
|
||
}
|
||
#endif// ROOBO_DUAL_MIC_ALGORITHM
|
||
#endif
|
||
}
|
||
}
|
||
|
||
static void roobo_asr_handler(void *priv)
|
||
{
|
||
short read_buf[ROOBO_ASR_INPUT_SHORT_LEN]; //buf大小与 frame_size 相等
|
||
int result = 0;
|
||
char text[32];
|
||
float score = 0;
|
||
|
||
for (;;) {
|
||
os_sem_pend(&__this->asr_sem, 0);
|
||
|
||
while (cbuf_get_data_size(&__this->asr_cbuf) >= ROOBO_ASR_INPUT_SHORT_LEN * 2) {
|
||
if (0 == cbuf_read(&__this->asr_cbuf, (void *)read_buf, sizeof(read_buf))) {
|
||
break;
|
||
}
|
||
|
||
result = roobo_asr_process(read_buf, ROOBO_ASR_INPUT_SHORT_LEN, text, &score);
|
||
if (result == 1) {
|
||
printf("2asr ok score = %f, text = %s", score, text);
|
||
wtk_handler(text);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static bool roobo_audiolib_init(void)
|
||
{
|
||
int ret = 0;
|
||
|
||
do {
|
||
ret = roobo_aec_init(__this->fig_aec_buf, NULL);
|
||
if (ret) {
|
||
printf("init aec failed\n");
|
||
ret = -2;
|
||
break;
|
||
} else {
|
||
printf("aec init ok\n");
|
||
}
|
||
|
||
ret = roobo_asr_init(NULL);
|
||
if (ret) {
|
||
printf("init asr failed\n");
|
||
ret = -3;
|
||
break;
|
||
} else {
|
||
printf("init asr ok\n");
|
||
}
|
||
} while (0);
|
||
|
||
return ret;
|
||
}
|
||
|
||
int aisp_open(u16 sample_rate)
|
||
{
|
||
if (roobo_audiolib_init()) {
|
||
printf("roobo_audiolib init failed\n");
|
||
return -1;
|
||
}
|
||
|
||
os_sem_create(&__this->sem, 0);
|
||
os_sem_create(&__this->asr_sem, 0);
|
||
cbuf_init(&__this->asr_cbuf, __this->asr_buf, sizeof(__this->asr_buf));
|
||
|
||
os_sem_create(&__this->aec_sem, 0);
|
||
cbuf_init(&__this->aec_cbuf, __this->aec_buf, sizeof(__this->aec_buf));
|
||
|
||
thread_fork("roobo_asr_handler", 3, 1024, 0, NULL, roobo_asr_handler, NULL);
|
||
#if ROOBO_DUAL_MIC_ALGORITHM
|
||
thread_fork("roobo_aec_handler", 3, 5632, 0, NULL, roobo_aec_handler, NULL);
|
||
#else
|
||
thread_fork("roobo_aec_handler", 3, 5120, 0, NULL, roobo_aec_handler, NULL);
|
||
#endif
|
||
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
linein_record_start(sample_rate);
|
||
#endif
|
||
mic_record_start(sample_rate);
|
||
|
||
__this->sample_rate = sample_rate;
|
||
__this->run_flag = 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
void aisp_suspend(void)
|
||
{
|
||
union audio_req req = {0};
|
||
|
||
__this->run_flag = 0;
|
||
|
||
os_sem_post(&__this->aec_sem);
|
||
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
//关闭enc_server
|
||
if (__this->linein_enc) {
|
||
req.enc.cmd = AUDIO_ENC_CLOSE;
|
||
server_request(__this->linein_enc, AUDIO_REQ_ENC, &req);
|
||
server_close(__this->linein_enc);
|
||
__this->linein_enc = NULL;
|
||
}
|
||
cbuf_clear(&__this->linein_cbuf);
|
||
#endif
|
||
//关闭enc_server
|
||
if (__this->mic_enc) {
|
||
req.enc.cmd = AUDIO_ENC_CLOSE;
|
||
server_request(__this->mic_enc, AUDIO_REQ_ENC, &req);
|
||
server_close(__this->mic_enc);
|
||
__this->mic_enc = NULL;
|
||
}
|
||
|
||
cbuf_clear(&__this->mic_cbuf);
|
||
cbuf_clear(&__this->aec_cbuf);
|
||
cbuf_clear(&__this->asr_cbuf);
|
||
}
|
||
|
||
void aisp_resume(void)
|
||
{
|
||
cbuf_clear(&__this->mic_cbuf);
|
||
cbuf_clear(&__this->aec_cbuf);
|
||
cbuf_clear(&__this->asr_cbuf);
|
||
|
||
os_sem_set(&__this->sem, 0);
|
||
os_sem_set(&__this->asr_sem, 0);
|
||
os_sem_set(&__this->aec_sem, 0);
|
||
|
||
#ifndef CONFIG_AISP_DIFFER_MIC_REPLACE_LINEIN
|
||
cbuf_clear(&__this->linein_cbuf);
|
||
linein_record_start(__this->sample_rate);
|
||
#endif
|
||
mic_record_start(__this->sample_rate);
|
||
|
||
__this->run_flag = 1;
|
||
}
|
||
|
||
int asr_read_input(u8 *buf, u32 len)
|
||
{
|
||
u32 rlen = 0;
|
||
|
||
do {
|
||
if (!__this->run_flag) {
|
||
return 0;
|
||
}
|
||
rlen = cbuf_read(&__this->aec_cbuf, buf, len);
|
||
if (rlen == len) {
|
||
break;
|
||
}
|
||
os_sem_pend(&__this->aec_sem, 0);
|
||
} while (!rlen);
|
||
|
||
return rlen;
|
||
}
|
||
|
||
void *get_asr_read_input_cb(void)
|
||
{
|
||
if (!__this->run_flag) {
|
||
return NULL;
|
||
}
|
||
|
||
os_sem_set(&__this->aec_sem, 0);
|
||
cbuf_clear(&__this->aec_cbuf);
|
||
return (void *)&asr_read_input;
|
||
}
|
||
|
||
#endif
|
||
|