This commit is contained in:
lmx
2025-10-29 13:10:02 +08:00
commit 49a07fa419
2284 changed files with 642060 additions and 0 deletions

View File

@ -0,0 +1,172 @@
#include "jl_kws_common.h"
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
//===================================================//
// 算法接口函数 //
//===================================================//
#define JL_KWS_PARAM_FILE SDFILE_RES_ROOT_PATH"jl_kws.cfg"
#define KWS_FRAME_LEN 320
void *JL_kws_init(void *ptr, void *fp1, int online_cmvn, float confidence_yes, float confidence_no, int smooth_yes, int smooth_no);
extern int jl_kws_get_need_buf_len(void);
//每帧固定320 bytes, 16k采样率, 10ms
extern int jl_detect_kws(char *data, int len, void *jl_kws1);
extern void JL_kws_free(void *_jl_det_kws);
#define ALIGN(a, b) \
({ \
int m = (u32)(a) & ((b)-1); \
int rets = (u32)(a) + (m?((b)-m):0); \
rets;\
})
//===================================================//
// IO 口DEBUG(测量算法时间) //
//===================================================//
#define KWS_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
#define KWS_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
/*
*Yes/No词条识别阈值:
*(1)越大越难识别,相应的,词条识别匹配度就越高,即越不容易误触发
*(2)越小越容易识别,相应的,词条识别匹配度就越低,即越容易误触发
*/
#define KWS_YES_THR 0.6f
#define KWS_NO_THR 0.6f
struct jl_kws_algo {
void *kws_handle;
void *kws_algo_buf;
u32 *frame_buf;
void *param_ptr;
};
static struct jl_kws_algo __kws_algo = {0};
static void kws_algo_local_init(void *buf, void *param_ptr)
{
//===============================//
// 算法初始化 //
//===============================//
void *buf_align = (void *)ALIGN(buf, 4);
kws_info("file ptr: 0x%x, buf_align: 0x%x", (u32)param_ptr, (u32)buf_align);
memset(buf, 0, jl_kws_get_need_buf_len());
int cmn_online = 1;
//int online_cmvn = 1;
int smooth_yes = 25;
int smooth_no = 30;
float confidence_yes = KWS_YES_THR;
float confidence_no = KWS_NO_THR;
__kws_algo.kws_handle = JL_kws_init(buf_align, param_ptr, cmn_online, confidence_yes, confidence_no, smooth_yes, smooth_no);
}
int jl_kws_algo_init(void)
{
FILE *fp = NULL;
struct vfs_attr param_attr = {0};
u32 param_len = 0;
u8 *param_ptr = NULL;
u32 need_buf_len = 0 ;
void *buf_ptr = NULL;
int ret = 0;
//===============================//
// 打开参数文件 //
//===============================//
fp = fopen(JL_KWS_PARAM_FILE, "r");
if (!fp) {
return -ENOENT;
}
fget_attrs(fp, &param_attr);
param_len = param_attr.fsize;
__kws_algo.param_ptr = (void *)param_attr.sclust; //cpu access addr
fclose(fp);
//===============================//
// 申请算法需要的buf //
//===============================//
need_buf_len = jl_kws_get_need_buf_len();
buf_ptr = zalloc(need_buf_len);
kws_debug("need_buf_len = 0x%x", need_buf_len);
if (!buf_ptr) {
return JL_KWS_ERR_ALGO_NO_BUF;
}
__kws_algo.kws_algo_buf = buf_ptr;
buf_ptr = zalloc(KWS_FRAME_LEN);
kws_debug("KWS_FRAME_LEN = 0x%x", KWS_FRAME_LEN);
if (!buf_ptr) {
free(__kws_algo.kws_algo_buf);
__kws_algo.kws_algo_buf = NULL;
return JL_KWS_ERR_ALGO_NO_BUF;
}
__kws_algo.frame_buf = buf_ptr;
kws_algo_local_init(__kws_algo.kws_algo_buf, __kws_algo.param_ptr);
return JL_KWS_ERR_NONE;
}
int jl_kws_algo_detect_run(u8 *buf, u32 len)
{
int ret = 0;
/* local_irq_disable(); */
/* KWS_IO_DEBUG_1(A,4); */
ret = jl_detect_kws((char *)buf, len, __kws_algo.kws_handle);
/* KWS_IO_DEBUG_0(A,4); */
/* local_irq_enable(); */
if ((ret != KWS_VOICE_EVENT_YES) &&
(ret != KWS_VOICE_EVENT_NO)) {
ret = KWS_VOICE_EVENT_NONE;
}
return ret;
}
void *jl_kws_algo_get_frame_buf(u32 *buf_len)
{
if (__kws_algo.frame_buf) {
*buf_len = KWS_FRAME_LEN;
return __kws_algo.frame_buf;
}
return NULL;
}
int jl_kws_algo_start(void)
{
return JL_KWS_ERR_NONE;
}
void jl_kws_algo_stop(void)
{
return;
}
void jl_kws_algo_close(void)
{
kws_info("%s", __func__);
if (__kws_algo.kws_handle) {
JL_kws_free(__kws_algo.kws_handle);
__kws_algo.kws_handle = NULL;
}
if (__kws_algo.kws_algo_buf) {
free(__kws_algo.kws_algo_buf);
__kws_algo.kws_algo_buf = NULL;
}
if (__kws_algo.frame_buf) {
free(__kws_algo.frame_buf);
__kws_algo.frame_buf = NULL;
}
}
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */

View File

@ -0,0 +1,15 @@
#ifndef _JL_KWS_API_H_
#define _JL_KWS_API_H_
int jl_kws_speech_recognition_open(void);
int jl_kws_speech_recognition_start(void);
void jl_kws_speech_recognition_stop(void);
void jl_kws_speech_recognition_close(void);
void jl_kws_main_user_demo(void);
//for jl_kws audio extern input
u8 kws_aec_get_state(void);
void kws_aec_data_output(void *priv, s16 *data, int len);
#endif /* #ifndef _JL_KWS_API_H_ */

View File

@ -0,0 +1,301 @@
#include "jl_kws_common.h"
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
#include "audio_enc.h"
#include "asm/audio_adc.h"
#include "audio_codec_clock.h"
//===================================================//
// ADC buf配置 //
//===================================================//
#define ADC_DEMO_BUF_NUM 2
#define ADC_DEMO_IRQ_POINTS 256
#define ADC_DEMO_BUFS_SIZE (ADC_DEMO_BUF_NUM * ADC_DEMO_IRQ_POINTS)
#define KWS_CBUF_SIZE (ADC_DEMO_BUFS_SIZE * sizeof(s16))
//==============================================//
// KWS 数据来自外部输入(AEC)配置 //
//==============================================//
#ifdef CONFIG_EARPHONE_CASE_ENABLE
#define TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN 1 //配置为1, 不需要本地开MIC, 由AEC外部输入
#else
#define TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN 0 //配置为0, 需要本地开MIC
#endif /* #ifdef CONFIG_EARPHONE_CASE_ENABLE */
//==============================================//
// KWS RAM使用OVERLAY配置 //
//==============================================//
#define KWS_USE_OVERLAY_RAM_ENABLE 0
#define KWS_USE_OVERLAY_RAM_SIZE (35 * 1024)
#if KWS_USE_OVERLAY_RAM_ENABLE
static int kws_ram[KWS_USE_OVERLAY_RAM_SIZE / sizeof(int)] sec(.jl_kws_ram);
#endif /* #if KWS_USE_OVERLAY_RAM_ENABLE */
enum KWS_AUDIO_STATE {
KWS_AUDIO_STATE_IDLE = 0,
KWS_AUDIO_STATE_RUN,
KWS_AUDIO_STATE_STOP,
KWS_AUDIO_STATE_CLOSE,
};
struct kws_adc_mic {
struct audio_adc_output_hdl adc_output;
struct adc_mic_ch mic_ch;
s16 adc_buf[ADC_DEMO_BUFS_SIZE]; //align 4Bytes
};
struct jl_kws_audio {
u8 kws_audio_state;
OS_SEM rx_sem;
struct kws_adc_mic *kws_adc;
cbuffer_t kws_cbuf;
u32 cbuf[KWS_CBUF_SIZE / 4];
};
static struct jl_kws_audio *__kws_audio = NULL;
extern struct audio_adc_hdl adc_hdl;
static void kws_adc_mic_output(void *priv, s16 *data, int len)
{
int wlen = 0;
local_irq_disable();/*防止关闭kws时kws任务和aec任务互相打断导致释放信号量错误死机的问题*/
if (__kws_audio == NULL) {
local_irq_enable();
return;
}
if (__kws_audio->kws_audio_state != KWS_AUDIO_STATE_RUN) {
local_irq_enable();
return;
}
/* kws_putchar('w'); */
wlen = cbuf_write(&(__kws_audio->kws_cbuf), data, len);
if (wlen < len) {
kws_info("kws cbuf full");
} else {
//kws_debug("wlen: %d", wlen);
}
os_sem_post(&(__kws_audio->rx_sem));
local_irq_enable();
}
static int jl_kws_adc_mic_open(void)
{
u16 mic_sr = 16000;
u8 mic_gain = 10;
if (__kws_audio->kws_adc != NULL) {
return JL_KWS_ERR_AUDIO_MIC_STATE_ERR;
}
__kws_audio->kws_adc = zalloc(sizeof(struct kws_adc_mic));
kws_debug("struct kws_adc_mic = 0x%x", (u32)sizeof(struct kws_adc_mic));
if (__kws_audio->kws_adc == NULL) {
return JL_KWS_ERR_AUDIO_MIC_NO_BUF;
}
kws_debug("kws local open mic");
//audio_mic_pwr_ctl(MIC_PWR_ON);
audio_adc_mic_open(&(__kws_audio->kws_adc->mic_ch), AUDIO_ADC_MIC_CH, &adc_hdl);
audio_adc_mic_set_sample_rate(&(__kws_audio->kws_adc->mic_ch), mic_sr);
audio_adc_mic_set_gain(&(__kws_audio->kws_adc->mic_ch), mic_gain);
audio_adc_mic_set_buffs(&(__kws_audio->kws_adc->mic_ch), __kws_audio->kws_adc->adc_buf, ADC_DEMO_IRQ_POINTS * 2, ADC_DEMO_BUF_NUM);
__kws_audio->kws_adc->adc_output.handler = kws_adc_mic_output;
audio_adc_add_output_handler(&adc_hdl, &(__kws_audio->kws_adc->adc_output));
return JL_KWS_ERR_NONE;
}
static int kws_speech_recognition_local_mic_open(void)
{
jl_kws_adc_mic_open();
jl_kws_audio_start();
return 0;
}
//==========================================================//
// JL_KWS AUDIO API //
//==========================================================//
int jl_kws_audio_init(void)
{
int ret = JL_KWS_ERR_NONE;
if (__kws_audio != NULL) {
return JL_KWS_ERR_AUDIO_INIT_STATE_ERR;
}
__kws_audio = zalloc(sizeof(struct jl_kws_audio));
kws_debug("struct jl_kws_audio = 0x%x", (u32)sizeof(struct jl_kws_audio));
if (__kws_audio == NULL) {
return JL_KWS_ERR_AUDIO_MIC_NO_BUF;
}
os_sem_create(&(__kws_audio->rx_sem), 0);
cbuf_init(&(__kws_audio->kws_cbuf), __kws_audio->cbuf, KWS_CBUF_SIZE);
audio_codec_clock_set(AUDIO_KWS_MODE, AUDIO_CODING_MSBC, 0);
return ret;
}
u8 kws_aec_get_state(void)
{
#if TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN
if (__kws_audio) {
//aec初始化, 查询是否进入kws模式, 这时有可能需要kws本身打开了mic需要close
if (__kws_audio->kws_adc) {
kws_debug("kws free adc buf");
audio_adc_mic_close(&__kws_audio->kws_adc->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &(__kws_audio->kws_adc->adc_output));
free(__kws_audio->kws_adc);
__kws_audio->kws_adc = NULL;
cbuf_clear(&(__kws_audio->kws_cbuf));
os_sem_set(&(__kws_audio->rx_sem), 0);
}
return 1;
} else {
return 0;
}
#else
return 0;
#endif /* #if TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN */
}
u8 kws_get_state(void)
{
return kws_aec_get_state();
}
u8 kws_is_running(void)
{
return (__kws_audio != NULL);
}
__attribute__((weak))
int audio_aec_update(u8 EnableBit)
{
return 0;
}
void kws_aec_data_output(void *priv, s16 *data, int len)
{
if (__kws_audio == NULL) {
return ;
}
if (__kws_audio->kws_adc) {
audio_adc_del_output_handler(&adc_hdl, &__kws_audio->kws_adc->adc_output);
kws_debug("kws free adc buf");
free(__kws_audio->kws_adc);
__kws_audio->kws_adc = NULL;
}
kws_adc_mic_output(priv, data, len);
}
int jl_kws_audio_get_data(void *buf, u32 len)
{
int ret = 0;
u32 data_len = 0;
u32 rlen = 0;
if (__kws_audio == NULL) {
return 0;
}
data_len = cbuf_get_data_len(&(__kws_audio->kws_cbuf));
if (data_len >= len) {
cbuf_read(&(__kws_audio->kws_cbuf), buf, len);
rlen = len;
} else {
os_sem_set(&(__kws_audio->rx_sem), 0);
#if TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN
ret = os_sem_pend(&(__kws_audio->rx_sem), 100);
if (ret == OS_TIMEOUT) {
kws_speech_recognition_local_mic_open();
}
#else
os_sem_pend(&(__kws_audio->rx_sem), portMAX_DELAY);
#endif /* #if TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN */
}
return rlen;
}
int jl_kws_audio_start(void)
{
int ret = JL_KWS_ERR_NONE;
kws_debug("%s", __func__);
__kws_audio->kws_audio_state = KWS_AUDIO_STATE_RUN;
#if (TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN == 0)
ret = jl_kws_adc_mic_open();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
#endif /* #if TCFG_JL_KWS_AUDIO_DATA_FROM_EXTERN */
if (__kws_audio && (__kws_audio->kws_adc)) {
audio_adc_mic_start(&(__kws_audio->kws_adc->mic_ch));
}
return ret;
}
void jl_kws_audio_stop(void)
{
if (__kws_audio) {
__kws_audio->kws_audio_state = KWS_AUDIO_STATE_STOP;
if (__kws_audio->kws_adc) {
audio_adc_mic_close(&__kws_audio->kws_adc->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &(__kws_audio->kws_adc->adc_output));
free(__kws_audio->kws_adc);
__kws_audio->kws_adc = NULL;
}
cbuf_clear(&(__kws_audio->kws_cbuf));
os_sem_set(&(__kws_audio->rx_sem), 0);
}
}
void jl_kws_audio_close(void)
{
kws_debug("%s", __func__);
if (__kws_audio) {
__kws_audio->kws_audio_state = KWS_AUDIO_STATE_CLOSE;
if (__kws_audio->kws_adc) {
audio_adc_mic_close(&__kws_audio->kws_adc->mic_ch);
audio_adc_del_output_handler(&adc_hdl, &(__kws_audio->kws_adc->adc_output));
free(__kws_audio->kws_adc);
__kws_audio->kws_adc = NULL;
}
audio_codec_clock_del(AUDIO_KWS_MODE);
extern u8 audio_aec_status(void);
if (audio_aec_status()) {
audio_aec_update(0);
}
free(__kws_audio);
__kws_audio = NULL;
}
}
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */

View File

@ -0,0 +1,70 @@
#ifndef _JL_KWS_COMMON_H_
#define _JL_KWS_COMMON_H_
#include "includes.h"
#include "app_config.h"
// #ifdef SUPPORT_MS_EXTENSIONS
// #pragma bss_seg( ".jl_kws_bss")
// #pragma data_seg( ".jl_kws_data")
// #pragma const_seg( ".jl_kws_const")
// #pragma code_seg( ".jl_kws_code")
// #endif
#define kws_info printf
#define KWS_DEBUG_ENABLE
#ifdef KWS_DEBUG_ENABLE
#define kws_debug printf
#define kws_putchar putchar
#else
#define kws_debug(...)
#define kws_putchar(...)
#endif /* #define KWS_DEBUG_ENABLE */
enum JL_KWS_ERR {
JL_KWS_ERR_NONE = 0,
JL_KWS_ERR_AUDIO_MIC_NO_BUF = -400,
JL_KWS_ERR_AUDIO_INIT_STATE_ERR,
JL_KWS_ERR_AUDIO_MIC_STATE_ERR,
JL_KWS_ERR_ALGO_NO_BUF = -300,
JL_KWS_ERR_ALGO_NO_FRAME_BUF,
};
enum KWS_VOICE_EVENT {
KWS_VOICE_EVENT_NONE = 0,
KWS_VOICE_EVENT_YES = 2,
KWS_VOICE_EVENT_NO,
};
//========================================//
// jl_kws_algo API //
//========================================//
extern int jl_kws_algo_init(void);
extern int jl_kws_algo_detect_run(u8 *buf, u32 len);
extern void *jl_kws_algo_get_frame_buf(u32 *buf_len);
extern int jl_kws_algo_start(void);
extern void jl_kws_algo_close(void);
extern void jl_kws_algo_stop(void);
//========================================//
// jl_kws_audio API //
//========================================//
extern int jl_kws_audio_init(void);
extern int jl_kws_audio_start(void);
extern void jl_kws_audio_stop(void);
extern void jl_kws_audio_close(void);
extern int jl_kws_audio_get_data(void *buf, u32 len);
//========================================//
// jl_kws_event API //
//========================================//
extern int jl_kws_event_init(void);
extern void jl_kws_event_stop(void);
extern void jl_kws_event_close(void);
extern void jl_kws_event_state_update(u8 voice_event);
#endif /* #ifndef _JL_KWS_COMMON_H_ */

View File

@ -0,0 +1,113 @@
#include "jl_kws_common.h"
#include "btstack/avctp_user.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif /* #if TCFG_USER_TWS_ENABLE */
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
//=========================================================//
// KWS 事件处理 //
//=========================================================//
struct jl_kws_event {
u32 last_event_jiffies;
u8 last_event;
};
static struct jl_kws_event __kws_event = {0};
static void kws_event_handle(u8 voice_event)
{
u32 cur_jiffies = jiffies;
if (voice_event == __kws_event.last_event) {
if (jiffies_to_msecs(cur_jiffies - __kws_event.last_event_jiffies) < 1000) {
kws_info("voice event %d same, ignore", voice_event);
__kws_event.last_event_jiffies = cur_jiffies;
return;
}
}
__kws_event.last_event_jiffies = cur_jiffies;
__kws_event.last_event = voice_event;
kws_info("%s: %d", __func__, voice_event);
switch (voice_event) {
case KWS_VOICE_EVENT_YES:
kws_info("send ANSWER cmd");
user_send_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL);
break;
case KWS_VOICE_EVENT_NO:
kws_info("send HANGUP cmd");
user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL);
break;
default:
break;
}
return;
}
//==========================================================//
// TWS 消息同步 //
//==========================================================//
#if TCFG_USER_TWS_ENABLE
extern bool get_tws_sibling_connect_state(void);
#define TWS_FUNC_ID_KWS_EVENT_SYNC TWS_FUNC_ID('K', 'W', 'S', 'V')
static void kws_event_sync_tws_state_deal(void *_data, u16 len, bool rx)
{
u8 *data = (u8 *)_data;
u8 voice_event = data[0];
kws_info("tws event rx sync: %d", voice_event);
kws_event_handle(voice_event);
}
static void kws_sync_tws_event(u8 voice_event)
{
if (get_tws_sibling_connect_state() == TRUE) {
tws_api_send_data_to_sibling(&voice_event, 1, TWS_FUNC_ID_KWS_EVENT_SYNC);
}
}
REGISTER_TWS_FUNC_STUB(kws_voice_event_sync) = {
.func_id = TWS_FUNC_ID_KWS_EVENT_SYNC,
.func = kws_event_sync_tws_state_deal,
};
#endif /* #if TCFG_USER_TWS_ENABLE */
//==========================================================//
// JL_KWS EVENT API //
//==========================================================//
int jl_kws_event_init(void)
{
return JL_KWS_ERR_NONE;
}
void jl_kws_event_stop(void)
{
return;
}
void jl_kws_event_close(void)
{
return;
}
void jl_kws_event_state_update(u8 voice_event)
{
#if TCFG_USER_TWS_ENABLE
if (get_tws_sibling_connect_state() == TRUE) {
kws_sync_tws_event(voice_event);
} else
#endif /* #if TCFG_USER_TWS_ENABLE */
{
kws_event_handle(voice_event);
}
}
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */

View File

@ -0,0 +1,306 @@
#include "jl_kws_common.h"
#include "jl_kws_api.h"
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
//==========================================================//
// KWS 语音识别 //
//==========================================================//
struct kws_speech_recognition {
u8 task_init;
u8 kws_state;
u8 kws_task_state;
};
static struct kws_speech_recognition jl_kws = {0};
//==============================================//
// KWS CPU频率配置 //
//==============================================//
#define KWS_BT_CALL_SYS_FREQUENCE_HZ (48 * 1000000)
#define __this (&jl_kws)
enum KWS_TASK_MSG {
KWS_SPEECH_RECOGNITION_RUN = 1,
KWS_SPEECH_RECOGNITION_STOP,
KWS_SPEECH_RECOGNITION_CLOSE,
};
enum KWS_STATE {
KWS_STATE_IDLE = 0,
KWS_STATE_INIT,
KWS_STATE_RUN,
KWS_STATE_STOP,
KWS_STATE_CLOSE,
};
enum KWS_TASK_STATE {
KWS_TASK_STATE_IDLE = 0,
KWS_TASK_STATE_INIT,
KWS_TASK_STATE_RUN,
KWS_TASK_STATE_STOP,
KWS_TASK_STATE_CLOSE,
};
//=======================================================//
// jl_kws_main //
//=======================================================//
//=========== 线程名称
#define THIS_TASK_NAME "kws"
static int kws_speech_recognition_run(void)
{
void *rbuf = 0;
u32 rbuf_len = 0;
u32 audio_data_len = 0;
int ret = JL_KWS_ERR_NONE;
int event = KWS_VOICE_EVENT_NONE;
kws_info("%s", __func__);
ret = jl_kws_audio_start();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
ret = jl_kws_algo_start();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
__this->kws_task_state = KWS_TASK_STATE_RUN;
while (1) {
if (__this->kws_state != KWS_STATE_RUN) {
break;
}
rbuf = jl_kws_algo_get_frame_buf(&rbuf_len);
if (rbuf == NULL) {
ret = JL_KWS_ERR_ALGO_NO_FRAME_BUF;
break;
}
audio_data_len = jl_kws_audio_get_data(rbuf, rbuf_len);
if (audio_data_len == rbuf_len) {
/* kws_putchar('r'); */
event = jl_kws_algo_detect_run(rbuf, rbuf_len);
if (event != KWS_VOICE_EVENT_NONE) {
jl_kws_event_state_update(event);
}
}
}
return ret;
}
static int jl_kws_speech_recognition_init(void)
{
kws_info("%s", __func__);
//1.算法初始化
int ret = 0;
ret = jl_kws_algo_init();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
//2.Audio MIC初始化
ret = jl_kws_audio_init();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
//3. event初始化
ret = jl_kws_event_init();
if (ret != JL_KWS_ERR_NONE) {
return ret;
}
return JL_KWS_ERR_NONE;
}
static int kws_speech_recognition_stop(void)
{
kws_info("%s", __func__);
if (__this->task_init) {
jl_kws_algo_stop();
jl_kws_audio_stop();
jl_kws_event_stop();
__this->kws_task_state = KWS_TASK_STATE_STOP;
}
return JL_KWS_ERR_NONE;
}
static void kws_speech_recognition_close(void)
{
kws_info("%s", __func__);
if (__this->task_init) {
jl_kws_algo_close();
jl_kws_audio_close();
jl_kws_event_close();
__this->kws_task_state = KWS_TASK_STATE_CLOSE;
//task_kill(THIS_TASK_NAME);
}
return;
}
static void kws_speech_recognition_task(void *param)
{
int msg[16];
int ret = 0;
kws_info("%s", __func__);
if (param) {
os_sem_post((OS_SEM *)(param)); //wait task ready sem
}
ret = jl_kws_speech_recognition_init();
kws_debug("ret = %d", ret);
if (ret != JL_KWS_ERR_NONE) {
kws_speech_recognition_close();
__this->task_init = 0;
task_kill(THIS_TASK_NAME);
}
__this->kws_state = KWS_STATE_INIT;
__this->kws_task_state = KWS_TASK_STATE_INIT;
while (1) {
ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
if (ret == OS_TASKQ) {
switch (msg[1]) {
case KWS_SPEECH_RECOGNITION_RUN:
kws_speech_recognition_run();
break;
case KWS_SPEECH_RECOGNITION_STOP:
kws_speech_recognition_stop();
break;
case KWS_SPEECH_RECOGNITION_CLOSE:
kws_speech_recognition_close();
os_sem_post((OS_SEM *)msg[2]);
break;
default:
break;
}
}
}
}
static u8 kws_idle_query(void)
{
return !(__this->kws_task_state == KWS_TASK_STATE_RUN);
}
REGISTER_LP_TARGET(kws_lp_target) = {
.name = "kws",
.is_idle = kws_idle_query,
};
//==========================================================//
// JL_KWS MAIN API //
//==========================================================//
int jl_kws_speech_recognition_open(void)
{
kws_info("%s", __func__);
OS_SEM ready_sem;
if (__this->task_init == 0) {
__this->task_init = 1;
os_sem_create(&ready_sem, 0);
task_create(kws_speech_recognition_task, (void *)&ready_sem, THIS_TASK_NAME);
//wait task ready
os_sem_pend(&ready_sem, 20);
}
return 0;
}
int jl_kws_speech_recognition_start(void)
{
int ret;
kws_info("%s", __func__);
if (__this->task_init) {
if (__this->kws_state == KWS_STATE_RUN) {
return 0;
}
__this->kws_state = KWS_STATE_RUN;
ret = os_taskq_post_msg(THIS_TASK_NAME, 1, KWS_SPEECH_RECOGNITION_RUN);
}
return 0;
}
void jl_kws_speech_recognition_stop(void)
{
int ret;
kws_info("%s", __func__);
if (__this->task_init) {
if (__this->kws_state == KWS_STATE_STOP) {
return;
}
__this->kws_state = KWS_STATE_STOP;
ret = os_taskq_post_msg(THIS_TASK_NAME, 1, KWS_SPEECH_RECOGNITION_STOP);
}
}
void jl_kws_speech_recognition_close(void)
{
kws_info("%s", __func__);
OS_SEM del_sem;
if (__this->task_init) {
if (__this->kws_state == KWS_STATE_CLOSE) {
return;
}
__this->kws_state = KWS_STATE_CLOSE;
os_sem_create(&del_sem, 0);
os_taskq_post_msg(THIS_TASK_NAME, 2, KWS_SPEECH_RECOGNITION_CLOSE, (void *)&del_sem);
os_sem_pend(&del_sem, 0xffff);
task_kill(THIS_TASK_NAME);
__this->task_init = 0;
}
}
//==========================================================//
// 测试代码 //
//==========================================================//
void jl_kws_main_user_demo(void)
{
//1.打开jl_kws模块
jl_kws_speech_recognition_open();
//2.在某时刻开始识别
os_time_dly(1000);
jl_kws_speech_recognition_start();
//3.在某时刻之后停止识别
os_time_dly(1500);
jl_kws_speech_recognition_stop();
//4.在某时刻之后重新开启识别
os_time_dly(2000);
jl_kws_speech_recognition_start();
//5.在某时刻之后关闭jl_kws模块
os_time_dly(2500);
jl_kws_speech_recognition_close();
}
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */