Files
Linux_Drivers/middleware/v2/sample/audio/cvi_sample_audio_rtos.c
sam.xiang 89f501af2a [middleware] add cvitek's multimedia framework
Change-Id: Iffc3cf32b99b95ba3ba534081a97881a2e004a14
2023-03-10 20:36:18 +08:00

478 lines
13 KiB
C

/*
* Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
*
* File Name: sample/cvi_sample_audio_rtos.c
* Description:example for audio api flow
* such as audio in, audio out, audio trancode flow
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
//add for audio kernel mode sample test case
//headers for cviaduio_core.ko & cvi_rtos_cmdqu.ko
#include "cviaudio_ioctl_cmd.h"
#include "rtos_cmdqu.h"
#include "cviaudio_kernel_mode.h"
#include "cvi_sys.h"
//define macro check
#ifndef SMP_AUD_UNUSED_REF
#define SMP_AUD_UNUSED_REF(X) ((X) = (X))
#endif
#ifdef AUD_SUPPORT_KERNEL_MODE
static int _console_request(char *printout, int defalut_val);
static int GET_CONSOLE_REQ(int status, char *printout, int default_val);
static CVI_BOOL _update_vqe_setting(AI_TALKVQE_CONFIG_S *pstAiVqeTalkAttr);
static CVI_BOOL _update_aec_setting(AI_TALKVQE_CONFIG_S *pstAiVqeTalkAttr);
#define _CONSOLE_REQ(X, Y) GET_CONSOLE_REQ(0, (char *)X, (int)Y)
//globacl variable for kernel module fd
CVI_S32 s32AudioCoreKer;
static CVI_BOOL _update_aec_setting(AI_TALKVQE_CONFIG_S *pstAiVqeTalkAttr)
{
if (pstAiVqeTalkAttr == NULL)
return CVI_FALSE;
AI_AEC_CONFIG_S default_AEC_Setting;
memset(&default_AEC_Setting, 0, sizeof(AI_AEC_CONFIG_S));
default_AEC_Setting.para_aec_filter_len = 13;
default_AEC_Setting.para_aes_std_thrd = 37;
default_AEC_Setting.para_aes_supp_coeff = 60;
pstAiVqeTalkAttr->stAecCfg = default_AEC_Setting;
pstAiVqeTalkAttr->u32OpenMask |= (LP_AEC_ENABLE | NLP_AES_ENABLE);
printf("pstAiVqeTalkAttr:u32OpenMask[0x%x]\n", pstAiVqeTalkAttr->u32OpenMask);
return CVI_FALSE;
}
static CVI_BOOL _update_vqe_setting(AI_TALKVQE_CONFIG_S *pstAiVqeTalkAttr)
{
if (pstAiVqeTalkAttr == NULL)
return CVI_FALSE;
pstAiVqeTalkAttr->u32OpenMask |= (NR_ENABLE|AGC_ENABLE|DCREMOVER_ENABLE);
AUDIO_AGC_CONFIG_S st_AGC_Setting;
AUDIO_ANR_CONFIG_S st_ANR_Setting;
st_AGC_Setting.para_agc_max_gain = 0;
st_AGC_Setting.para_agc_target_high = 2;
st_AGC_Setting.para_agc_target_low = 72;
st_AGC_Setting.para_agc_vad_ena = CVI_TRUE;
st_ANR_Setting.para_nr_snr_coeff = 15;
st_ANR_Setting.para_nr_init_sile_time = 0;
pstAiVqeTalkAttr->stAgcCfg = st_AGC_Setting;
pstAiVqeTalkAttr->stAnrCfg = st_ANR_Setting;
pstAiVqeTalkAttr->para_notch_freq = 0;
printf("pstAiVqeTalkAttr:u32OpenMask[0x%x]\n", pstAiVqeTalkAttr->u32OpenMask);
return CVI_TRUE;
}
static int _console_request(char *printout, int default_val)
{
char s_option[128];
int s32Ret = -1;
printf("\e[0;32m=====================================\n");
fflush(stdout);
fflush(stdin);
if (printout != NULL) {
printf(printout);
fgets(s_option, 10, stdin);
if (s_option[0] == '\n') {
s32Ret = default_val;
printf("input default val[%d]\n", s32Ret);
} else {
s32Ret = atoi(s_option);
printf("input [%d]\n", s32Ret);
}
} else
printf("Error input type[%s][%d]\n", __func__, __LINE__);
printf("\e[0;32m=====================================\n");
fflush(stdin);
return s32Ret;
}
static int GET_CONSOLE_REQ(int audio_status, char *printout, int default_val)
{
if (audio_status) {
printf("[Error]Not support [%s][%d]\n", __func__, __LINE__);
return 0;
} else {
return _console_request(printout, default_val);
}
return 0;
}
CVI_VOID SAMPLE_AUDIO_Usage(CVI_VOID)
{
printf("\n\n/Usage:./sample_audio <index>/\n");
printf("\tindex and its function list below\n");
printf("\t1: SAMPLE_AUDIO_RTOS_UNIT_TEST_KERNEL_MODE\n");
printf("\t2: SAMPLE_AUDIO_RTOS_UNIT_TEST_BLOCK_MODE\n");
printf("\t3: SAMPLE_AUDIO_GET_AUDIO_FRAME_BY_FRAME_RTOS_SSP\n");
printf("\t4: For debug purpose\n");
}
/******************************************************************************/
/* function : main*/
/******************************************************************************/
void AUDIO_HandleSig(CVI_S32 signo)
{
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
if (SIGINT == signo || SIGTERM == signo) {
//destroy all thread
printf("\033[0;31mprogram exit abnormally!\033[0;39m\n");
}
exit(0);
}
CVI_S32 s32RtosCore;
static int devm_rtos_fd = -1;
CVI_S32 SAMPLE_AUDIO_RTOS_UNIT_TEST_BLOCK_MODE(void)
{
printf("File saving in kernel space after handler\n");
CVI_CHAR devName[255];
int ret = 0;
int counter = 0;
FILE *fd_user;
CVI_S32 s32Ret;
CVI_U64 u64PhyAddr = 0;
CVI_VOID *pVirAddr = NULL;
//char *tmp = NULL;
//printf("[%s][%d]...\n", __func__, __LINE__);
CVI_SYS_Init();
printf("[%s][%d]Using ion buffer for phy/vir addr request...\n", __func__, __LINE__);
sprintf(devName, "/dev/%s", RTOS_CMDQU_DEV_NAME);
s32RtosCore = open(devName, O_RDWR | O_DSYNC);
printf("open device (%s) fd: %d\n", devName, s32RtosCore);
if (s32RtosCore <= 0) {
printf("open device (%s) FAILURE: %d\n", devName, __LINE__);
return CVI_FAILURE;
} else
printf("open device (%s) SUCCESS: %d\n", devName, __LINE__);
if (devm_rtos_fd == -1) {
printf("open rtos devm for fd\n");
devm_rtos_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (devm_rtos_fd == -1) {
printf("[cviaudio][kernel_mode]cannot open '/dev/mem'\n");
}
}
//step 1: send init command
cmdqu_t cmdq;
memset(&cmdq, 0, sizeof(struct cmdqu_t));
//sys_cache_flush_p(SspRtosUnitTesCfgPhy, sizeof(ST_SSP_RTOS_INIT));
cmdq.ip_id = IP_AUDIO;
cmdq.cmd_id = CVIAUDIO_RTOS_CMD_SSP_UNIT_TEST_BLOCK_MODE_INIT;
cmdq.block = 1;
cmdq.resv.mstime = -1;
cmdq.param_ptr = 0;
printf("[%s][%d]...send init\n", __func__, __LINE__);
ret = ioctl(s32RtosCore, RTOS_CMDQU_SEND_WAIT, &cmdq);
printf("[%s][%d]...send init out\n", __func__, __LINE__);
if (ret)
printf("v][%s][%d]...ioctl error init\n", __func__, __LINE__);
//step 2: get the frame from file and save
memset(&cmdq, 0, sizeof(struct cmdqu_t));
fd_user = fopen("/tmp/user.raw", "wb");
//sys_cache_flush_p(SspRtosUnitTesCfgPhy, sizeof(ST_SSP_RTOS_INIT));
s32Ret = CVI_SYS_IonAlloc(&u64PhyAddr, &pVirAddr, "audiortos_unittest", 4*1024);
if (s32Ret) {
printf("CVI_SYS_IonAlloc failed >< with %#x\n", s32Ret);
return 0;
} else
printf("CVI_SYS_IonAlloc ok!!!\n");
while (counter < 2000) {
counter += 1;
cmdq.ip_id = IP_AUDIO;
cmdq.cmd_id = CVIAUDIO_RTOS_CMD_SSP_UNIT_TEST_BLOCK_MODE_GET;
cmdq.param_ptr = u64PhyAddr;//physical address
cmdq.block = 1;
cmdq.resv.mstime = 10000;
ret = ioctl(s32RtosCore, RTOS_CMDQU_SEND_WAIT, &cmdq);
if (ret) {
printf("[%s][%d]...ioctl error init\n", __func__, __LINE__);
break;
}
CVI_SYS_IonInvalidateCache(u64PhyAddr, pVirAddr, 4*1024);
//tmp = (char *)pVirAddr;
//printf("read out and check[%s][%d]...send init out[0x%x][0x%x][0x%x]\n",
// __func__, __LINE__, tmp[0], tmp[1], tmp[2]);
fwrite(pVirAddr, 1, 320, fd_user);
}
fclose(fd_user);
printf("[%s][%d]finished!!!\n", __func__, __LINE__);
return 0;
}
CVI_S32 SAMPLE_AUDIO_DEBUG(void)
{
CVI_CHAR devName[255];
int ret = 0;
#ifndef CVIAUDIO_CEO_DEV_NAME
#define CVIAUDIO_CEO_DEV_NAME "cviaudio_core"
#endif
sprintf(devName, "/dev/%s", CVIAUDIO_CEO_DEV_NAME);
s32AudioCoreKer = open(devName, O_RDWR | O_DSYNC);
printf("open device (%s) fd: %d\n", devName, s32AudioCoreKer);
if (s32AudioCoreKer <= 0) {
printf("open device (%s) FAILURE: %d\n", devName, __LINE__);
return CVI_FAILURE;
} else
printf("open device (%s) SUCCESS: %d\n", devName, __LINE__);
ret = ioctl(s32AudioCoreKer, CVIAUDIO_IOCTL_SSP_DEBUG, NULL);
if (ret != 0) {
printf("[Error]ioctl[%d] CVIAUDIO_IOCTL_SSP_DEBUG fail with %d\n",
CVIAUDIO_IOCTL_SSP_DEBUG, ret);
} else
printf("[cviaudio]CVIAUDIO_IOCTL_SSP_DEBUG success!!!\n");
return CVI_SUCCESS;
}
CVI_S32 SAMPLE_AUDIO_RTOS_UNIT_TEST_KERNEL_MODE(void)
{
CVI_CHAR devName[255];
int ret = 0;
#ifndef CVIAUDIO_CEO_DEV_NAME
#define CVIAUDIO_CEO_DEV_NAME "cviaudio_core"
#endif
sprintf(devName, "/dev/%s", CVIAUDIO_CEO_DEV_NAME);
s32AudioCoreKer = open(devName, O_RDWR | O_DSYNC);
printf("open device (%s) fd: %d\n", devName, s32AudioCoreKer);
if (s32AudioCoreKer <= 0) {
printf("open device (%s) FAILURE: %d\n", devName, __LINE__);
return CVI_FAILURE;
} else
printf("open device (%s) SUCCESS: %d\n", devName, __LINE__);
ret = ioctl(s32AudioCoreKer, CVIAUDIO_IOCTL_SSP_UNIT_TEST, NULL);
if (ret != 0) {
printf("[Error]ioctl[%d] CVIAUDIO_INIT_CHECK fail with %d\n",
CVIAUDIO_IOCTL_SSP_UNIT_TEST, ret);
goto KERNEL_MODE_ERR;
} else {
printf("[cviaudio][kernel_mode]Init Counter\n");
//s32Ret = CVI_SUCCESS;
}
printf("user space keep running ...!\n");
while (1) {
usleep(500);
}
KERNEL_MODE_ERR:
return CVI_FAILURE;
}
CVI_S32 SAMPLE_AUDIO_GET_AUDIO_FRAME_BY_FRAME_RTOS_SSP(CVI_VOID)
{
CVI_S32 s32Ret = CVI_SUCCESS;
CVI_S32 s32SampleRate = 0;
CVI_S32 s32PeriodSize = 0;
CVI_S32 s32RecSeconds = 0;
CVI_S32 s32RecLoops = 0;
AUDIO_FRAME_S stFrame;
CVI_BOOL bVqeOn = CVI_FALSE;
CVI_BOOL bAecOn = CVI_FALSE;
AI_TALKVQE_CONFIG_S stAiVqeTalkAttr;
AI_TALKVQE_CONFIG_S *pstAiVqeTalkAttr = (AI_TALKVQE_CONFIG_S *)&stAiVqeTalkAttr;
FILE *fp_rec = CVI_NULL;
//CVI_U64 u64PhyAddr = 0;
//CVI_VOID *pVirAddr = NULL;
memset(&stFrame, 0, sizeof(AUDIO_FRAME_S));
memset(&stAiVqeTalkAttr, 0, sizeof(AI_TALKVQE_CONFIG_S));
s32SampleRate = _CONSOLE_REQ("Enter sample rate(only support 8000/16000)\n",
8000);
s32PeriodSize = _CONSOLE_REQ("Enter period_size(in samples), ex 160/320/640\n",
160);
bVqeOn = (CVI_BOOL)_CONSOLE_REQ("bVqeOn? 0:No 1:Yes (default:0)\n", 0);
if (bVqeOn == CVI_FALSE)
pstAiVqeTalkAttr = NULL;
else {
if ((s32SampleRate == 8000) ||
(s32SampleRate == 16000)) {
_update_vqe_setting(pstAiVqeTalkAttr);
pstAiVqeTalkAttr->s32WorkSampleRate = s32SampleRate;
printf("Turn On AEC?\n");
bAecOn = (CVI_BOOL)_CONSOLE_REQ("bAecOn 0:No 1:Yes (default:0)\n", 0);
if (bAecOn == CVI_TRUE) {
_update_aec_setting(pstAiVqeTalkAttr);
printf("----------------notice-------------------------------\n");
printf("AEC will need to setup record in to channel Count = 2\n");
printf("AEC will output only one single channel with 2 channels in\n");
printf("-----------------------------------------------------\n");
}
} else {
//not support VQE aside of 8k/16k input
printf("VQE only support on 8k/16k sample rate\n");
bVqeOn = CVI_FALSE;
bAecOn = CVI_FALSE;
}
}
if (pstAiVqeTalkAttr)
printf("[%s]open_mask[0x%x]\n", __func__, pstAiVqeTalkAttr->u32OpenMask);
s32Ret = CVI_AI_EnableExtSSp(s32SampleRate, s32PeriodSize, pstAiVqeTalkAttr);
if (s32Ret != CVI_SUCCESS) {
printf("[Error][%s][%d]\n", __func__, __LINE__);
goto EXIT_TEST;
return CVI_FAILURE;
}
s32RecSeconds = 15;
s32RecLoops = (s32RecSeconds * s32SampleRate) / s32PeriodSize;
fp_rec = fopen("/tmp/sample_record.raw", "wb");
if (!fp_rec)
return CVI_FAILURE;
printf("force rec 15 seconds ---------------------->\n");
while (s32RecLoops--) {
s32Ret = CVI_AI_GetFrameExtSsp(&stFrame);
if (s32Ret != CVI_SUCCESS) {
printf("[Error][%s][%d]\n", __func__, __LINE__);
goto EXIT_TEST;
} else {
fwrite(stFrame.u64VirAddr[0], 1,
(stFrame.u32Len * 2), fp_rec);
}
}
if (fp_rec)
fclose(fp_rec);
//if (pVirAddr)
// CVI_SYS_IonFree(u64PhyAddr, pVirAddr);
s32Ret = CVI_AI_DisableExtSsp();
if (s32Ret != CVI_SUCCESS)
printf("[Error][%s][%d]\n", __func__, __LINE__);
printf("[%s]test...finished s32RecLoops[%d]!!!!!!!!!!!!!!!!!!!!\n", __func__, s32RecLoops);
return CVI_SUCCESS;
EXIT_TEST:
if (fp_rec)
fclose(fp_rec);
printf("[Error][%s]test...failure\n", __func__);
return CVI_FAILURE;
}
#endif
CVI_S32 main(int argc, char *argv[])
{
CVI_S32 s32Ret = CVI_SUCCESS;
CVI_U32 u32Index = 0;
#ifndef AUD_SUPPORT_KERNEL_MODE
printf("audio not suppot kernel mode in this chip!!\n");
SMP_AUD_UNUSED_REF(argc);
SMP_AUD_UNUSED_REF(argv);
SMP_AUD_UNUSED_REF(s32Ret);
SMP_AUD_UNUSED_REF(u32Index);
return CVI_FAILURE;
#else
printf("auido support kernel mode with cviaudio_core.ko insert first\n");
if (argc < 2) {
SAMPLE_AUDIO_Usage();
return CVI_FAILURE;
}
u32Index = atoi(argv[1]);
if (u32Index > 6) {
printf("Wrong option[%d]...\n", u32Index);
SAMPLE_AUDIO_Usage();
return CVI_FAILURE;
}
signal(SIGINT, AUDIO_HandleSig);
signal(SIGTERM, AUDIO_HandleSig);
printf("sample_audio_rtos:Enter command id =[%d]\n", u32Index);
switch (u32Index) {
case 1: {
printf("test ssp unit test in cviaudio_core.ko and freeRtos\n");
SAMPLE_AUDIO_RTOS_UNIT_TEST_KERNEL_MODE();
break;
}
case 2: {
printf("test ssp unit test in cvi_rtos_cmd.ko and freeRtos\n");
SAMPLE_AUDIO_RTOS_UNIT_TEST_BLOCK_MODE();
break;
}
case 3: {
printf("[sample code]recording frame by frame with external RTOS SSP\n");
SAMPLE_AUDIO_GET_AUDIO_FRAME_BY_FRAME_RTOS_SSP();
break;
}
case 4: {
SAMPLE_AUDIO_DEBUG();
break;
}
default: {
printf("Invalid input command[%d]\n", u32Index);
break;
}
}
return s32Ret;
#endif
}