doubao_chat/apps/common/asr/jlkws/jlkws.c

299 lines
7.5 KiB
C

#include "server/audio_server.h"
#include "server/server_core.h"
#include "generic/circular_buf.h"
#include "os/os_api.h"
#include "event.h"
#include "app_config.h"
#include "jlsp_far_keyword.h"
#include "event/key_event.h"
/* #include "jlsp_kws_aec.h" */
#if (defined CONFIG_ASR_ALGORITHM) && (CONFIG_ASR_ALGORITHM == JLKWS_ALGORITHM)
const int CONFIG_KWS_RAM_USE_ENABLE = 1;
extern void aisp_resume(void);
#define ONCE_SR_POINTS 160//256
#define AISP_BUF_SIZE (ONCE_SR_POINTS * 2) //跑不过来时适当加大倍数
#define MIC_SR_LEN (ONCE_SR_POINTS * 2)
#ifdef CONFIG_AEC_ENC_ENABLE
/*aec module enable bit define*/
#define AEC_EN BIT(0)
#define NLP_EN BIT(1)
#define ANS_EN BIT(2)
#define AEC_MODE_ADVANCE (AEC_EN | NLP_EN | ANS_EN)
#define AEC_MODE_REDUCE (NLP_EN | ANS_EN)
#define AEC_MODE_SIMPLEX (ANS_EN)
#endif
static struct {
int pid;
u16 sample_rate;
u8 volatile exit_flag;
int volatile run_flag;
OS_SEM sem;
s16 mic_buf[AISP_BUF_SIZE * 2];
void *mic_enc;
cbuffer_t mic_cbuf;
} aisp_server;
#define __this (&aisp_server)
static const float confidence[8] = {
0.5, 0.5, 0.5, 0.5, //小杰小杰,小杰同学,播放音乐,暂停播放
0.5, 0.5, 0.5, 0.5, //增大音量,减小音量,上一首, 下一首
};
enum {
PLAY_MUSIC_EVENT = 4,
STOP_MUSIC_EVENT,
VOLUME_INC_EVENT = 7,
VOLUME_DEC_EVENT,
SONG_PREVIOUS_EVENT,
SONG_NEXT_EVENT,
};
static void aisp_task(void *priv)
{
u32 mic_len, linein_len;
u32 time = 0, time_cnt = 0, cnt = 0;
int ret;
int model = 0;
int model_size, private_heap_size, share_heap_size;
void *kws = NULL;
u8 *private_heap = NULL, *share_heap = NULL;
int online = 0;
jl_far_kws_model_get_heap_size(model, &model_size, &private_heap_size, &share_heap_size);
private_heap = zalloc(private_heap_size);
if (!private_heap) {
goto __exit;
}
share_heap = zalloc(share_heap_size);
if (!share_heap) {
goto __exit;
}
kws = jl_far_kws_model_init(model, private_heap, private_heap_size, share_heap, share_heap_size, model_size, confidence, online);
if (!kws) {
goto __exit;
}
aisp_resume();
while (1) {
if (__this->exit_flag) {
break;
}
if (!__this->run_flag) {
os_sem_pend(&__this->sem, 0);
continue;
}
if (__this->exit_flag) {
break;
}
if ((cbuf_get_data_size(&__this->mic_cbuf) < ONCE_SR_POINTS * 2)) {
os_sem_pend(&__this->sem, 0);
continue;
}
short near_data_buf[ONCE_SR_POINTS];
mic_len = cbuf_read(&__this->mic_cbuf, near_data_buf, ONCE_SR_POINTS * 2);
if (!mic_len) {
continue;
}
time = timer_get_ms();
ret = jl_far_kws_model_process(kws, model, (u8 *)near_data_buf, sizeof(near_data_buf));
if (ret > 1) {
printf("++++++++++++++++++ %d ++++++++++++++++++\n", ret);
//add your button event according to ret
struct key_event key = {0};
if (ret == PLAY_MUSIC_EVENT) {
key.action = KEY_EVENT_UP;
key.value = KEY_LOCAL;
} else if (ret == STOP_MUSIC_EVENT) {
key.action = KEY_EVENT_HOLD;
key.value = KEY_LOCAL;
} else if (ret == VOLUME_INC_EVENT) {
key.action = KEY_EVENT_CLICK;
key.value = KEY_DOWN;
} else if (ret == VOLUME_DEC_EVENT) {
key.action = KEY_EVENT_CLICK;
key.value = KEY_UP;
} else if (ret == SONG_PREVIOUS_EVENT) {
key.action = KEY_EVENT_LONG;
key.value = KEY_UP;
} else if (ret == SONG_NEXT_EVENT) {
key.action = KEY_EVENT_LONG;
key.value = KEY_DOWN;
}
key.type = KEY_EVENT_USER;
key_event_notify(KEY_EVENT_FROM_USER, &key);
jl_far_kws_model_reset(kws);
}
time_cnt += timer_get_ms() - time;
if (++cnt == 100) {
printf("aec time :%d \n", time_cnt);
time_cnt = cnt = 0;
}
}
__exit:
if (kws) {
jl_far_kws_model_free(kws);
}
if (private_heap) {
free(private_heap);
}
if (share_heap) {
free(share_heap);
}
__this->run_flag = 0;
}
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 aisp_vfs_fwrite(void *file, void *data, u32 len)
{
cbuffer_t *cbuf = (cbuffer_t *)file;
u32 wlen = cbuf_write(cbuf, data, len);
if (wlen != len) {
cbuf_clear(&__this->mic_cbuf);
puts("busy!\n");
}
os_sem_set(&__this->sem, 0);
os_sem_post(&__this->sem);
return len;
}
static int aisp_vfs_fclose(void *file)
{
return 0;
}
static const struct audio_vfs_ops aisp_vfs_ops = {
.fwrite = aisp_vfs_fwrite,
.fclose = aisp_vfs_fclose,
};
int aisp_open(u16 sample_rate)
{
__this->exit_flag = 0;
__this->mic_enc = server_open("audio_server", "enc");
server_register_event_handler(__this->mic_enc, NULL, enc_server_event_handler);
cbuf_init(&__this->mic_cbuf, __this->mic_buf, sizeof(__this->mic_buf));
os_sem_create(&__this->sem, 0);
__this->sample_rate = sample_rate;
return thread_fork("aisp", 3, 2048, 0, &__this->pid, aisp_task, __this);
}
void aisp_suspend(void)
{
union audio_req req = {0};
if (!__this->run_flag) {
return;
}
__this->run_flag = 0;
req.enc.cmd = AUDIO_ENC_STOP;
server_request(__this->mic_enc, AUDIO_REQ_ENC, &req);
cbuf_clear(&__this->mic_cbuf);
}
void aisp_resume(void)
{
union audio_req req = {0};
if (__this->run_flag) {
return;
}
__this->run_flag = 1;
os_sem_set(&__this->sem, 0);
os_sem_post(&__this->sem);
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = 1;
req.enc.channel_bit_map = BIT(CONFIG_AISP_MIC0_ADC_CHANNEL);
req.enc.frame_size = ONCE_SR_POINTS * 2 * req.enc.channel;
req.enc.volume = CONFIG_AISP_MIC_ADC_GAIN;
req.enc.sample_rate = __this->sample_rate;
req.enc.format = "pcm";
#if CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_PLNK0
req.enc.sample_source = "plnk0";
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_PLNK1
req.enc.sample_source = "plnk1";
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_IIS0
req.enc.sample_source = "iis0";
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_IIS1
req.enc.sample_source = "iis1";
#else
req.enc.sample_source = "mic";
#endif
req.enc.vfs_ops = &aisp_vfs_ops;
req.enc.output_buf_len = req.enc.frame_size * 3;
req.enc.file = (FILE *)&__this->mic_cbuf;
#ifdef CONFIG_AEC_ENC_ENABLE
struct aec_s_attr aec_param = {0};
aec_param.EnableBit = AEC_MODE_ADVANCE;
aec_param.output_way = 0; //1:使用硬件回采 0:使用软件回采
req.enc.aec_attr = &aec_param;
req.enc.aec_enable = 0; //默认不开
#endif
server_request(__this->mic_enc, AUDIO_REQ_ENC, &req);
}
void aisp_close(void)
{
if (__this->exit_flag) {
return;
}
aisp_suspend();
__this->exit_flag = 1;
os_sem_post(&__this->sem);
if (__this->mic_enc) {
server_close(__this->mic_enc);
__this->mic_enc = NULL;
}
thread_kill(&__this->pid, KILL_WAIT);
}
#endif