318 lines
8.1 KiB
C
318 lines
8.1 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
||
#pragma bss_seg(".user_asr.data.bss")
|
||
#pragma data_seg(".user_asr.data")
|
||
#pragma const_seg(".user_asr.text.const")
|
||
#pragma code_seg(".user_asr.text")
|
||
#endif
|
||
/*****************************************************************
|
||
>file name : user_asr.c
|
||
>create time : Thu 23 Dec 2021 10:00:58 AM CST
|
||
>用户自定义语音识别算法平台接入
|
||
*****************************************************************/
|
||
#include "app_config.h"
|
||
#include "system/includes.h"
|
||
#include "user_asr.h"
|
||
#include "smart_voice.h"
|
||
#include "voice_mic_data.h"
|
||
|
||
|
||
#if ((defined TCFG_AUDIO_ASR_DEVELOP) && (TCFG_AUDIO_ASR_DEVELOP == ASR_CFG_USER_DEFINED))
|
||
|
||
#define ASR_FRAME_SAMPLES 160 /*语音识别帧长(采样点)*/
|
||
|
||
/*debug调试*/
|
||
#define SMART_VOICE_TEST_PRINT_PCM 0
|
||
#define SMART_VOICE_TEST_WRITE_FILE 0
|
||
|
||
#define SMART_VOICE_SAMPLE_RATE 16000
|
||
#define SMART_VOICE_REC_MIC_SECS 2 /*记录声音时长*/
|
||
#define SMART_VOICE_REC_DATA_LEN (SMART_VOICE_SAMPLE_RATE * SMART_VOICE_REC_MIC_SECS * 2)
|
||
|
||
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
#define VOICE_DATA_BUFFER_SIZE 16 * 1024
|
||
#elif SMART_VOICE_TEST_PRINT_PCM
|
||
#define VOICE_DATA_BUFFER_SIZE SMART_VOICE_REC_DATA_LEN
|
||
#else
|
||
#define VOICE_DATA_BUFFER_SIZE 2 * 1024
|
||
#endif
|
||
|
||
|
||
struct user_platform_asr_context {
|
||
void *mic;
|
||
void *core;
|
||
u8 data_enable;
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
void *file;
|
||
#endif
|
||
};
|
||
|
||
extern const int config_user_asr_enable;
|
||
static struct user_platform_asr_context *__this = NULL;
|
||
|
||
|
||
static void user_voice_mic_data_debug_stop_handler(struct user_platform_asr_context *sv);
|
||
static inline void user_voice_data_write_file(struct user_platform_asr_context *asr, void *data, int len);
|
||
static void user_voice_mic_data_debug_start(struct user_platform_asr_context *asr);
|
||
|
||
|
||
/*
|
||
* 算法引擎打开函数
|
||
*/
|
||
static void *user_asr_core_open(int sample_rate)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
* 算法引擎关闭函数
|
||
*/
|
||
static void user_asr_core_close(void *core)
|
||
{
|
||
|
||
}
|
||
|
||
/*
|
||
* 算法引擎数据处理
|
||
*/
|
||
static int user_asr_core_data_handler(void *core, void *data, int len)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
*********************************************************************
|
||
* user asr data handler
|
||
* Description: 用户算法平台平台语音识别数据处理
|
||
* Arguments : asr - 语音识别数据管理结构
|
||
* Return : 0 - 处理成功, 非0 - 处理失败.
|
||
* Note(s) : 该函数通过读取mic数据送入算法引擎完成语音帧.
|
||
*********************************************************************
|
||
*/
|
||
static int user_asr_data_handler(struct user_platform_asr_context *asr)
|
||
{
|
||
if (!asr->mic) {
|
||
return -EINVAL;
|
||
}
|
||
|
||
#if SMART_VOICE_TEST_PRINT_PCM
|
||
putchar('*');
|
||
return 1;
|
||
#endif
|
||
|
||
s16 data[ASR_FRAME_SAMPLES];
|
||
|
||
int len = voice_mic_data_read(asr->mic, data, sizeof(data));
|
||
if (len < sizeof(data)) {
|
||
return -EINVAL;
|
||
}
|
||
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
user_voice_data_write_file(asr, data, sizeof(data));
|
||
#else
|
||
if (asr->core) {
|
||
user_asr_core_data_handler(asr->core, data, sizeof(data));
|
||
}
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
*********************************************************************
|
||
* user_asr core handler
|
||
* Description: 用户自定义语音识别处理
|
||
* Arguments : priv - 语音识别私有数据
|
||
* taskq_type - TASK消息类型
|
||
* msg - 消息存储指针(对应自身模块post的消息)
|
||
* Return : None.
|
||
* Note(s) : 音频平台资源控制以及ASR主要识别算法引擎.
|
||
*********************************************************************
|
||
*/
|
||
int user_asr_core_handler(void *priv, int taskq_type, int *msg)
|
||
{
|
||
struct user_platform_asr_context *asr = (struct user_platform_asr_context *)priv;
|
||
int err = ASR_CORE_STANDBY;
|
||
|
||
if (taskq_type != OS_TASKQ) {
|
||
return err;
|
||
}
|
||
|
||
switch (msg[0]) {
|
||
case SMART_VOICE_MSG_MIC_OPEN: /*语音识别打开 - MIC打开,算法引擎打开*/
|
||
/* msg[1] - MIC数据源,msg[2] - 音频采样率,msg[3] - mic的数据总缓冲长度*/
|
||
asr->mic = voice_mic_data_open(msg[1], msg[2], msg[3]);
|
||
if (!asr->mic) {
|
||
printf("asr mic open failed.\n");
|
||
}
|
||
asr->core = user_asr_core_open(msg[2]);
|
||
asr->data_enable = 1;
|
||
err = ASR_CORE_WAKEUP;
|
||
break;
|
||
case SMART_VOICE_MSG_SWITCH_SOURCE:
|
||
/*这里进行MIC的数据源切换 (主系统MIC或VAD MIC)*/
|
||
|
||
break;
|
||
case SMART_VOICE_MSG_WAKE:
|
||
err = ASR_CORE_WAKEUP;
|
||
putchar('W');
|
||
user_voice_mic_data_debug_start(asr);
|
||
asr->data_enable = 1;
|
||
break;
|
||
case SMART_VOICE_MSG_STANDBY:
|
||
asr->data_enable = 0;
|
||
user_voice_mic_data_debug_stop_handler(asr);
|
||
if (asr->mic) {
|
||
voice_mic_data_clear(asr->mic);
|
||
}
|
||
break;
|
||
case SMART_VOICE_MSG_MIC_CLOSE: /*语音识别关闭 - MIC关闭,算法引擎关闭*/
|
||
asr->data_enable = 0;
|
||
/* msg[2] - 信号量*/
|
||
voice_mic_data_close(asr->mic);
|
||
asr->mic = NULL;
|
||
user_asr_core_close(asr->core);
|
||
asr->core = NULL;
|
||
asr->data_enable = 0;
|
||
os_sem_post((OS_SEM *)msg[1]);
|
||
break;
|
||
case SMART_VOICE_MSG_DMA: /*MIC通路数据DMA消息*/
|
||
asr->data_enable = 1;
|
||
err = ASR_CORE_WAKEUP;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (asr->data_enable) {
|
||
err = user_asr_data_handler(asr);
|
||
err = err ? ASR_CORE_STANDBY : ASR_CORE_WAKEUP;
|
||
}
|
||
return err;
|
||
}
|
||
|
||
int user_platform_asr_open(void)
|
||
{
|
||
if (!config_user_asr_enable) {
|
||
return 0;
|
||
}
|
||
int err = 0;
|
||
struct user_platform_asr_context *asr = (struct user_platform_asr_context *)zalloc(sizeof(struct user_platform_asr_context));
|
||
|
||
if (!asr) {
|
||
return -ENOMEM;
|
||
}
|
||
|
||
err = smart_voice_core_create(asr);
|
||
if (err != OS_NO_ERR) {
|
||
goto __err;
|
||
}
|
||
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
extern void force_set_sd_online(char *sdx);
|
||
force_set_sd_online("sd0");
|
||
void *mnt = mount("sd0", "storage/sd0", "fat", 3, NULL);
|
||
if (!mnt) {
|
||
printf("sd0 mount fat failed.\n");
|
||
goto __err;
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* 推送MIC的资源打开到语音识别主任务
|
||
* V1.1.0版本支持了低功耗VAD MIC的使用,需要可以改为VAD MIC
|
||
*
|
||
*/
|
||
smart_voice_core_post_msg(4, SMART_VOICE_MSG_MIC_OPEN, VOICE_MCU_MIC, VOICE_DATA_BUFFER_SIZE, SMART_VOICE_SAMPLE_RATE);
|
||
|
||
__this = asr;
|
||
return 0;
|
||
__err:
|
||
if (asr) {
|
||
free(asr);
|
||
}
|
||
return err;
|
||
}
|
||
|
||
void user_platform_asr_close(void)
|
||
{
|
||
if (!config_user_asr_enable) {
|
||
return;
|
||
}
|
||
if (__this) {
|
||
OS_SEM *sem = (OS_SEM *)malloc(sizeof(OS_SEM));
|
||
os_sem_create(sem, 0);
|
||
smart_voice_core_post_msg(2, SMART_VOICE_MSG_MIC_CLOSE, (int)sem);
|
||
os_sem_pend(sem, 0);
|
||
free(sem);
|
||
smart_voice_core_free();
|
||
free(__this);
|
||
__this = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
void user_voice_mic_data_debug_stop(void)
|
||
{
|
||
smart_voice_core_post_msg(1, SMART_VOICE_MSG_STANDBY);
|
||
}
|
||
|
||
|
||
static void user_voice_mic_data_debug_stop_handler(struct user_platform_asr_context *asr)
|
||
{
|
||
#if SMART_VOICE_TEST_PRINT_PCM
|
||
if (asr->mic) {
|
||
voice_mic_data_dump(asr->mic);
|
||
}
|
||
#endif
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
if (asr->file) {
|
||
fclose(asr->file);
|
||
asr->file = NULL;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static inline void user_voice_data_write_file(struct user_platform_asr_context *asr, void *data, int len)
|
||
{
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
if (asr->file) {
|
||
int ret = fwrite(data, len, 1, asr->file);
|
||
if (ret <= 0) {
|
||
printf("%s write error!!!", __func__);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
static void user_voice_mic_data_debug_start(struct user_platform_asr_context *asr)
|
||
{
|
||
#if SMART_VOICE_TEST_WRITE_FILE
|
||
asr->file = fopen("storage/sd0/C/AudioVAD/vad***.raw", "w+");
|
||
if (!asr->file) {
|
||
printf("Open file failed, can not test.\n");
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
static u8 user_asr_idle_query(void)
|
||
{
|
||
if (__this) {
|
||
return !__this->data_enable;
|
||
} else {
|
||
return 1;
|
||
}
|
||
}
|
||
REGISTER_LP_TARGET(user_asr_lp_target) = {
|
||
.name = "smart_voice",
|
||
.is_idle = user_asr_idle_query,
|
||
};
|
||
|
||
int audio_smart_voice_check_status(void)
|
||
{
|
||
return (__this ? true : false);
|
||
}
|
||
|
||
#endif
|