299 lines
7.5 KiB
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
|
|
|