Files
AC707N/SDK/audio/smart_voice/user_asr.c
T
2025-12-03 11:12:34 +08:00

318 lines
8.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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