630 lines
18 KiB
C
Raw Normal View History

2025-05-14 11:26:23 +08:00
// Copyright 2023-2024 Beken
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifdef ILOCK_AI_ASR
#include "stdio.h"
#include <os/os.h>
#include <os/mem.h>
#include <os/str.h>
#include <modules/pm.h>
//#include "audio_record.h"
#include "bk_wanson_asr.h"
#include "cli.h"
#include "wanson_client.h"
#include "audio_record.h"
#include "aud_intf.h"
#include "aud_intf_types.h"
#define TAG "ws_asr_test"
#if defined(CONFIG_FATFS)
#include "diskio.h"
static FIL mic_file;
static char mic_file_name[50];
static FATFS *pfs = NULL;
static bk_err_t tf_mount(void)
{
FRESULT fr;
if (pfs != NULL)
{
os_free(pfs);
}
pfs = os_malloc(sizeof(FATFS));
if(NULL == pfs)
{
BK_LOGI(TAG, "f_mount malloc failed!\r\n");
return BK_FAIL;
}
fr = f_mount(pfs, "1:", 1);
if (fr != FR_OK)
{
BK_LOGE(TAG, "f_mount failed:%d\r\n", fr);
return BK_FAIL;
}
else
{
BK_LOGI(TAG, "f_mount OK!\r\n");
}
return BK_OK;
}
static bk_err_t tf_unmount(void)
{
FRESULT fr;
fr = f_unmount(DISK_NUMBER_SDIO_SD, "1:", 1);
if (fr != FR_OK)
{
BK_LOGE(TAG, "f_unmount failed:%d\r\n", fr);
return BK_FAIL;
}
else
{
BK_LOGI(TAG, "f_unmount OK!\r\n");
}
if (pfs)
{
os_free(pfs);
pfs = NULL;
}
return BK_OK;
}
#endif
#define WANSON_CLIENT_USE_UAC 1
static bool wanson_asr_running = false;
static beken_thread_t wanson_asr_task_hdl = NULL;
static beken_semaphore_t wanson_asr_sem = NULL;
static wanson_asr_handle_t gl_wanson_asr = NULL;
//static audio_record_t *gl_aud_record = NULL;
static bk_err_t wanson_asr_test_exit(void)
{
wanson_asr_running = false;
if (gl_wanson_asr)
{
bk_wanson_asr_destroy(gl_wanson_asr);
}
// if (gl_aud_record)
// {
// audio_record_destroy(gl_aud_record);
// }
return BK_OK;
}
static int wanson_asr_result_notify_handle(wanson_asr_handle_t wanson_asr, char *result, void *params)
{
BK_LOGE("%s \n", result);
if (os_strcmp(result, "小蜂管家") == 0) //识别出唤醒词 小蜂管家
{
BK_LOGE("%s \n", "xiao feng guan jia ");
}
else if (os_strcmp(result, "阿尔米诺") == 0) //识别出唤醒词 阿尔米诺
{
BK_LOGE("%s \n", "a er mi nuo ");
}
else if (os_strcmp(result, "会客模式") == 0) //识别出 会客模式
{
BK_LOGE("%s \n", "hui ke mo shi ");
}
else if (os_strcmp(result, "用餐模式") == 0) //识别出 用餐模式
{
BK_LOGE("%s \n", "yong can mo shi ");
}
else if (os_strcmp(result, "离开模式") == 0) //识别出 离开模式
{
BK_LOGE("%s \n", "li kai mo shi ");
}
else if (os_strcmp(result, "回家模式") == 0) //识别出 回家模式
{
BK_LOGE("%s \n", "hui jia mo shi ");
}
else
{
//nothing
}
return BK_OK;
}
static int count = 0;
//static uint16_t pcm8K16b [480] ;
//static uint16_t pcm16K16b [960] ;
static int send_mic_data_to_sd(uint8_t *data, unsigned int len)
{
//BK_LOGE(TAG, "send_mic_data_to_sd:%d\n", len);
uint8_t sounds[len/2];
int pos = 0;
for(int i = 2 ;i<len ;i=i+4){
//int16_t value = (data[i] << 8) | data[i+1];
//bk_wanson_asr_data_write(gl_wanson_asr, (void *)data+i, 1);
//bk_wanson_asr_data_write(gl_wanson_asr, (void *)data+i+1, 1);
//little endian
sounds[pos] = data[i+i];
pos++;
sounds[pos] = data[i];
pos++;
}
#if 0
FRESULT fr;
uint32 uiTemp = 0;
/* write data to file */
fr = f_write(&mic_file, (void *)sounds, len/2, &uiTemp);
if (fr != FR_OK) {
BK_LOGE(TAG, "write %s fail.\r\n", mic_file_name);
}
BK_LOGE(TAG, "write count %d \r\n", count);
if(count >800){
/* close mic file */
f_close(&mic_file);
tf_unmount();
}
count++;
#endif
//BK_LOGE(TAG, "@@ %02X %02X %02X %02X %02X %02X\n", sounds[0], sounds[1],sounds[2],sounds[3],sounds[4],sounds[5]);
bk_wanson_asr_data_write(gl_wanson_asr, (void *)sounds, len/2);
#if 0
/*
8K8位转8K16位
//对8K8位采样的每个字节加上0x80再移位成2个字节
short sData16 = (( short )( byData8 + 0x80 )) << 8;
*/
/*
8K16位转8K8位
BYTE byData8 = ( BYTE )(( sData16 >> 8 ) - 0x80 );
*/
int pos = 0;
for(int i = 0 ;i<len; i++){
pcm8K16b[i] = (( short )( data[i] + 0x80 )) << 8 ;
// 插入插值样本:前一样本与当前样本的平均值
//int16_t interpolated = (sample16_prev + sample16_current) / 2;
//fwrite(&interpolated, sizeof(int16_t), 1, out);
//BK_LOGE(TAG, "pcm16K16b:%d\n", pos);
pcm16K16b[pos] = pcm8K16b[i];
pos++;
//BK_LOGE(TAG, "pcm16K16b:%d\n", pos);
pcm16K16b[pos] = pcm8K16b[i];
pos++;
//
// 写入当前样本
//fwrite(&sample16_current, sizeof(int16_t), 1, out);
}
BK_LOGE(TAG, "write count %d \r\n", count);
if(count >500){
/* close mic file */
f_close(&mic_file);
tf_unmount();
}
count++;
//bk_wanson_asr_data_write(gl_wanson_asr, (int16_t *)pcm16k, len);
//BK_LOGE(TAG, "%02X %02X %02X %02X %02X %02X\n", data[2], data[10],data[30],data[80],data[100],data[200]);
//bk_wanson_asr_data_write(gl_wanson_asr, (int16_t *)data, len/2);
//BK_LOGE(TAG, "%02X %02X %02X %02X %02X %02X\n", pcm16K16b[0], pcm16K16b[1],pcm16K16b[2],pcm16K16b[3],pcm16K16b[4],pcm16K16b[5]);
//bk_wanson_asr_data_write(gl_wanson_asr, (int16_t *)pcm16K16b, 960);
FRESULT fr;
uint32 uiTemp = 0;
/* write data to file */
fr = f_write(&mic_file, (void *)data, len, &uiTemp);
if (fr != FR_OK) {
BK_LOGE(TAG, "write %s fail.\r\n", mic_file_name);
}
#endif
return len;
}
#ifdef WANSON_CLIENT_USE_UAC
static int volume_adjust2(int16_t * in_buf, float in_vol)
{
int tmp;
// in_vol[0, 100]
float vol = in_vol - 98;
if(-98<vol && vol<0)
vol = 1/(vol*(-1));
else if(0<=vol && vol<=1)
vol = 1;
/*
else if(1<=vol && vol<=2)
vol = vol;
*/
else if(vol<=-98)
vol = 0;
else if(vol>=2)
vol = 30; //这个值可以根据你的实际情况去调整
tmp = (*in_buf)*vol; // 上面所有关于vol的判断其实都是为了此处*in_buf乘以一个倍数你可以根据自己的需要去修改
// 下面的code主要是为了溢出判断
if(tmp > 32767)
tmp = 32767;
else if(tmp < -32768)
tmp = -32768;
*in_buf = tmp;
return 0;
}
static int convert_8khz_to_16khz(void * dst_buf, void *src_buf, int src_size)
{
int i;
for(i=0; i<src_size/2; i++)
{
*((short *)dst_buf + i*2) = *((short *)src_buf + i);
volume_adjust2((short *)dst_buf + i*2,100);
*((short *)dst_buf + i*2 + 1) = *((short *)src_buf + i);
volume_adjust2((short *)dst_buf + i*2 + 1,100);
}
return src_size * 2;
}
//static uint16_t pcm8K16b [480] ;
//static uint8_t pcm16K16b [960] ;
static int send_uac_mic_data_to_sd(uint8_t *data, unsigned int len)
{
//UAC PCM signed 16bit ,little endian,8000k mono
if(count >800){
#if defined(CONFIG_FATFS)
/* close mic file */
f_close(&mic_file);
tf_unmount();
#endif
}else{
uint8_t pcm16K16b [len*2] ;
convert_8khz_to_16khz(&pcm16K16b,data,len);
bk_wanson_asr_data_write(gl_wanson_asr, (void *)pcm16K16b, len*2);
/*
FRESULT fr;
uint32 uiTemp = 0;
fr = f_write(&mic_file, (void *)pcm16K16b, len*2, &uiTemp);
if (fr != FR_OK) {
BK_LOGE(TAG, "write %s fail.\r\n", mic_file_name);
}
count++;
*/
}
return len;
}
void test(){
rtos_delay_milliseconds(3000);
//audio_tras_init();
bk_err_t ret = BK_OK;
aud_intf_drv_setup_t aud_intf_drv_setup = DEFAULT_AUD_INTF_DRV_SETUP_CONFIG();
aud_intf_drv_setup.aud_intf_tx_mic_data = send_uac_mic_data_to_sd;
ret = bk_aud_intf_drv_init(&aud_intf_drv_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_drv_init fail, ret:%d \r\n", ret);
} else {
BK_LOGE(TAG, "bk_aud_intf_drv_init complete \r\n");
}
ret = bk_aud_intf_set_mode(AUD_INTF_WORK_MODE_VOICE);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_set_mode fail, ret:%d \r\n", ret);
} else {
BK_LOGE(TAG, "bk_aud_intf_set_mode complete \r\n");
}
aud_intf_voc_setup_t aud_intf_voc_setup = DEFAULT_AUD_INTF_VOC_SETUP_CONFIG();
aud_intf_voc_setup.data_type = AUD_INTF_VOC_DATA_TYPE_PCM;
aud_intf_voc_setup.samp_rate = 8000;
aud_intf_voc_setup.spk_en = AUD_INTF_VOC_SPK_OPEN;
aud_intf_voc_setup.spk_mode = AUD_DAC_WORK_MODE_SIGNAL_END;
aud_intf_voc_setup.mic_type = AUD_INTF_MIC_TYPE_UAC;
aud_intf_voc_setup.spk_type = AUD_INTF_MIC_TYPE_UAC;
ret = bk_aud_intf_voc_init(aud_intf_voc_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_voc_init fail, ret:%d \r\n", ret);
} else {
BK_LOGE(TAG, "bk_aud_intf_voc_init complete \r\n");
}
ret = bk_aud_intf_voc_start();
}
#endif
static void wanson_asr_main(beken_thread_arg_t param_data)
{
#if defined(CONFIG_FATFS)
bk_err_t ret;
FRESULT fr;
#if 1
ret = tf_mount();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "tfcard mount fail, ret:%d\n", ret);
}
/*open file to save pcm data */
sprintf(mic_file_name, "1:/%s", "999.pcm");
fr = f_open(&mic_file, mic_file_name, FA_CREATE_ALWAYS | FA_WRITE);
if (fr != FR_OK) {
BK_LOGE(TAG, "open %s fail\n", mic_file_name);
}
#endif
#endif
char *mic_data_buff = NULL;
/* init audio record */
//audio_record_cfg_t record_config = DEFAULT_AUDIO_RECORD_CONFIG();
//record_config.sampRate = 16000;
//record_config.frame_size = 960;
//record_config.pool_size = 1920;
//gl_aud_record = audio_record_create(AUDIO_RECORD_ONBOARD_MIC, &record_config);
//if (!gl_aud_record)
//{
// BK_LOGE(TAG, "%s, %d, create audio record handle fail\n", __func__, __LINE__);
// goto fail;
//}
//BK_LOGI(TAG, "audio record create complete\n");
#ifdef WANSON_CLIENT_USE_UAC
test();
#elif
aud_intf_drv_setup_t aud_intf_drv_setup = DEFAULT_AUD_INTF_DRV_SETUP_CONFIG();
aud_intf_mic_setup_t aud_intf_mic_setup = DEFAULT_AUD_INTF_MIC_SETUP_CONFIG();
aud_intf_drv_setup.aud_intf_tx_mic_data = send_mic_data_to_sd;
ret = bk_aud_intf_drv_init(&aud_intf_drv_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_drv_init fail, ret:%d\n", ret);
goto fail;
}
ret = bk_aud_intf_set_mode(AUD_INTF_WORK_MODE_GENERAL);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_set_mode fail, ret:%d\n", ret);
goto fail;
}
aud_intf_mic_setup.mic_chl = AUD_INTF_MIC_CHL_DUAL;
aud_intf_mic_setup.samp_rate = 16000;//8000 16000
//aud_intf_mic_setup.mic_type = AUD_INTF_MIC_TYPE_UAC;
aud_intf_mic_setup.frame_size = 960;
//aud_intf_mic_setup.mic_gain = 0x2d;
ret = bk_aud_intf_mic_init(&aud_intf_mic_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_mic_init fail, ret:%d\n", ret);
goto fail;
}
BK_LOGE(TAG, "bk_aud_intf_mic_init OK:\n");
ret = bk_aud_intf_mic_start();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(TAG, "bk_aud_intf_mic_start fail, ret:%d\n", ret);
goto fail;
}
BK_LOGE(TAG, "bk_aud_intf_mic_start OK:\n");
#endif
//test();
wanson_asr_cfg_t asr_config = DEFAULT_WANSON_ASR_CONFIG();
asr_config.asr_result_notify = wanson_asr_result_notify_handle;
gl_wanson_asr = bk_wanson_asr_create(&asr_config);
if (!gl_wanson_asr)
{
BK_LOGE(TAG, "%s, %d, create wanson asr handle fail\n", __func__, __LINE__);
goto fail;
}
BK_LOGI(TAG, "audio wanson asr complete\n");
#ifdef CONFIG_BEKEN_WANSON_ASR_USE_SRAM
mic_data_buff = os_malloc(960);
#else
mic_data_buff = psram_malloc(960);
#endif
if (!mic_data_buff)
{
BK_LOGE(TAG, "%s, %d, malloc mic_data_buff: 960 fail\n", __func__, __LINE__);
goto fail;
}
os_memset(mic_data_buff, 0, 960);
bk_wanson_asr_start(gl_wanson_asr);
BK_LOGI(TAG, "wanson asr start complete\n");
//audio_record_open(gl_aud_record);
//BK_LOGI(TAG, "audio record open complete\n");
rtos_set_semaphore(&wanson_asr_sem);
wanson_asr_running = true;
while (wanson_asr_running)
{
//bk_err_t read_size = audio_record_read_data(gl_aud_record, mic_data_buff, 960);
bk_err_t read_size = 0;
if (read_size == 960)
{
int write_size = bk_wanson_asr_data_write(gl_wanson_asr, (int16_t *)mic_data_buff, 960);
if (write_size != 960)
{
BK_LOGE(TAG, "%s, %d, wanson_asr write size: %d != 960\n", __func__, __LINE__, write_size);
}
}
else
{
//BK_LOGE(TAG, "%s, %d, audio_record read size: %d != 960\n", __func__, __LINE__, read_size);
}
rtos_delay_milliseconds(500);
}
fail:
wanson_asr_running = false;
wanson_asr_test_exit();
if (mic_data_buff)
{
#ifdef CONFIG_BEKEN_WANSON_ASR_USE_SRAM
os_free(mic_data_buff);
#else
psram_free(mic_data_buff);
#endif
mic_data_buff = NULL;
}
rtos_set_semaphore(&wanson_asr_sem);
wanson_asr_task_hdl = NULL;
rtos_delete_thread(NULL);
}
static bk_err_t wanson_asr_test_start(void)
{
bk_err_t ret = BK_OK;
ret = rtos_init_semaphore(&wanson_asr_sem, 1);
if (ret != BK_OK)
{
BK_LOGE(TAG, "%s, %d, create semaphore fail\n", __func__, __LINE__);
return BK_FAIL;
}
ret = rtos_create_thread(&wanson_asr_task_hdl,
(BEKEN_DEFAULT_WORKER_PRIORITY - 1),
"audio_play",
(beken_thread_function_t)wanson_asr_main,
6*1024,
NULL);
if (ret != BK_OK)
{
BK_LOGE(TAG, "%s, %d, create wanson_asr_main task fail\n", __func__, __LINE__);
goto fail;
}
rtos_get_semaphore(&wanson_asr_sem, BEKEN_NEVER_TIMEOUT);
BK_LOGI(TAG, "%s, %d, create wanson_asr_main task complete\n", __func__, __LINE__);
return BK_OK;
fail:
if (wanson_asr_sem)
{
rtos_deinit_semaphore(&wanson_asr_sem);
wanson_asr_sem = NULL;
}
return BK_FAIL;
}
static bk_err_t wanson_asr_test_stop(void)
{
if (!wanson_asr_running)
{
BK_LOGW(TAG, "%s, %d, wanson_asr not work\n", __func__, __LINE__);
return BK_OK;
}
wanson_asr_running = false;
rtos_get_semaphore(&wanson_asr_sem, BEKEN_NEVER_TIMEOUT);
rtos_deinit_semaphore(&wanson_asr_sem);
wanson_asr_sem = NULL;
return BK_OK;
}
/*
static void cli_wanson_asr_test_help(void)
{
BK_LOGI(TAG, "wanson_asr_test {start|stop}\n");
}
void cli_wanson_asr_test_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
{
if (argc != 2)
{
cli_wanson_asr_test_help();
return;
}
if (os_strcmp(argv[1], "start") == 0)
{
wanson_asr_test_start();
}
else if (os_strcmp(argv[1], "stop") == 0)
{
wanson_asr_test_stop();
}
else
{
cli_wanson_asr_test_help();
}
}
#define WANSON_ASR_TEST_CMD_CNT (sizeof(s_wanson_asr_test_commands) / sizeof(struct cli_command))
static const struct cli_command s_wanson_asr_test_commands[] =
{
{"wanson_asr_test", "wanson_asr_test {start|stop}", cli_wanson_asr_test_cmd},
};
int cli_wanson_asr_test_init(void)
{
BK_LOGI(TAG, "cli_wanson_asr_test_init \n");
return cli_register_commands(s_wanson_asr_test_commands, WANSON_ASR_TEST_CMD_CNT);
}
*/
void poka_wanson_asr_test_init(){
wanson_asr_test_start();
}
#endif