目的:使海思板的麦克风和扬声器工作起来;让更多的爱好者了解海思、加入海思。
目录
1 准备工作
1)音频能力
2)检测板子
3)sample下audio编译
2 麦克风调试
1)配置acap音频参数
2)启动ai(关闭重采样及不使用VQE)
3)配置Audio Codec
4)取音频流
3 总结
我的板子就是MIC同时接了AC_INL和AC_INR,最后录音数据都是0数据。最后AC_INR接地就ok了。
声音调试是基于样例sample下audio(依赖common文件夹)
Hi3516CV500_SDK_V2.0.1.1/smp/a7_linux/mpp/sample
make ARCH=arm CROSS_COMPILE=arm-himix200-linux-
AIO_ATTR_S stAioAttr;
stAioAttr.enSamplerate = AUDIO_SAMPLE_RATE_48000;
stAioAttr.enBitwidth = AUDIO_BIT_WIDTH_16;
stAioAttr.enWorkmode = AIO_MODE_I2S_MASTER;
stAioAttr.enSoundmode = AUDIO_SOUND_MODE_MONO;
stAioAttr.u32EXFlag = 0;
stAioAttr.u32FrmNum = 30;
stAioAttr.u32PtNumPerFrm = AACLC_SAMPLES_PER_FRAME;
stAioAttr.u32ChnCnt = 1;
stAioAttr.u32ClkSel = 0;
stAioAttr.enI2sType = AIO_I2STYPE_INNERCODEC;
/******************************************************************************
* function : Start Ai
******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_StartAi(AUDIO_DEV AiDevId, HI_S32 s32AiChnCnt,
AIO_ATTR_S* pstAioAttr, AUDIO_SAMPLE_RATE_E enOutSampleRate, HI_BOOL bResampleEn, HI_VOID* pstAiVqeAttr, HI_U32 u32AiVqeType)
{
HI_S32 i;
HI_S32 s32Ret;
s32Ret = HI_MPI_AI_SetPubAttr(AiDevId, pstAioAttr);
if (s32Ret)
{
printf("%s: HI_MPI_AI_SetPubAttr(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
return s32Ret;
}
s32Ret = HI_MPI_AI_Enable(AiDevId);
if (s32Ret)
{
printf("%s: HI_MPI_AI_Enable(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
return s32Ret;
}
for (i = 0; i < s32AiChnCnt>>pstAioAttr->enSoundmode; i++)
{
s32Ret = HI_MPI_AI_EnableChn(AiDevId, i);
if (s32Ret)
{
printf("%s: HI_MPI_AI_EnableChn(%d,%d) failed with %#x\n", __FUNCTION__, AiDevId, i, s32Ret);
return s32Ret;
}
if (HI_TRUE == bResampleEn)
{
s32Ret = HI_MPI_AI_EnableReSmp(AiDevId, i, enOutSampleRate);
if (s32Ret)
{
printf("%s: HI_MPI_AI_EnableReSmp(%d,%d) failed with %#x\n", __FUNCTION__, AiDevId, i, s32Ret);
return s32Ret;
}
}
if (NULL != pstAiVqeAttr)
{
HI_BOOL bAiVqe = HI_TRUE;
switch (u32AiVqeType)
{
case 0:
s32Ret = HI_SUCCESS;
bAiVqe = HI_FALSE;
break;
case 1:
s32Ret = HI_MPI_AI_SetRecordVqeAttr(AiDevId, i, (AI_RECORDVQE_CONFIG_S *)pstAiVqeAttr);
break;
default:
s32Ret = HI_FAILURE;
break;
}
if (s32Ret)
{
printf("%s: SetAiVqe%d(%d,%d) failed with %#x\n", __FUNCTION__, u32AiVqeType, AiDevId, i, s32Ret);
return s32Ret;
}
if (bAiVqe)
{
s32Ret = HI_MPI_AI_EnableVqe(AiDevId, i);
if (s32Ret)
{
printf("%s: HI_MPI_AI_EnableVqe(%d,%d) failed with %#x\n", __FUNCTION__, AiDevId, i, s32Ret);
return s32Ret;
}
}
}
}
return HI_SUCCESS;
}
HI_S32 SAMPLE_INNER_CODEC_CfgAudio(AUDIO_SAMPLE_RATE_E enSample)
{
HI_S32 fdAcodec = -1;
HI_S32 ret = HI_SUCCESS;
ACODEC_FS_E i2s_fs_sel = 0;
int iAcodecInputVol = 0;
ACODEC_MIXER_E input_mode = 0;
fdAcodec = open(ACODEC_FILE, O_RDWR);
if (fdAcodec < 0)
{
printf("%s: can't open Acodec,%s\n", __FUNCTION__, ACODEC_FILE);
return HI_FAILURE;
}
if (ioctl(fdAcodec, ACODEC_SOFT_RESET_CTRL))
{
printf("Reset audio codec error\n");
}
switch (enSample)
{
case AUDIO_SAMPLE_RATE_8000:
i2s_fs_sel = ACODEC_FS_8000;
break;
case AUDIO_SAMPLE_RATE_16000:
i2s_fs_sel = ACODEC_FS_16000;
break;
case AUDIO_SAMPLE_RATE_32000:
i2s_fs_sel = ACODEC_FS_32000;
break;
case AUDIO_SAMPLE_RATE_11025:
i2s_fs_sel = ACODEC_FS_11025;
break;
case AUDIO_SAMPLE_RATE_22050:
i2s_fs_sel = ACODEC_FS_22050;
break;
case AUDIO_SAMPLE_RATE_44100:
i2s_fs_sel = ACODEC_FS_44100;
break;
case AUDIO_SAMPLE_RATE_12000:
i2s_fs_sel = ACODEC_FS_12000;
break;
case AUDIO_SAMPLE_RATE_24000:
i2s_fs_sel = ACODEC_FS_24000;
break;
case AUDIO_SAMPLE_RATE_48000:
i2s_fs_sel = ACODEC_FS_48000;
break;
case AUDIO_SAMPLE_RATE_64000:
i2s_fs_sel = ACODEC_FS_64000;
break;
case AUDIO_SAMPLE_RATE_96000:
i2s_fs_sel = ACODEC_FS_96000;
break;
default:
printf("%s: not support enSample:%d\n", __FUNCTION__, enSample);
ret = HI_FAILURE;
break;
}
if (ioctl(fdAcodec, ACODEC_SET_I2S1_FS, &i2s_fs_sel))
{
printf("%s: set acodec sample rate failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
/* set audio input config */
input_mode = ACODEC_MIXER_IN1;
if (ioctl(fdAcodec, ACODEC_SET_MIXER_MIC, &input_mode))
{
printf("%s: select acodec input_mode failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
// add by wei
HI_U32 u32MuteCtrl = 0;
if(ioctl(fdAcodec, ACODEC_SET_MICL_MUTE, &u32MuteCtrl))
{
printf("%s: select acodec mute_l failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
if(ioctl(fdAcodec, ACODEC_SET_MICR_MUTE, &u32MuteCtrl))
{
printf("%s: select acodec mute_r failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
// add by wei end
if (1) /* should be 1 when micin */ // change by wei from 0 to 1
{
/******************************************************************************************
The input volume range is [-87, +86]. Both the analog gain and digital gain are adjusted.
A larger value indicates higher volume.
For example, the value 86 indicates the maximum volume of 86 dB,
and the value -87 indicates the minimum volume (muted status).
The volume adjustment takes effect simultaneously in the audio-left and audio-right channels.
The recommended volume range is [+10, +56].
Within this range, the noises are lowest because only the analog gain is adjusted,
and the voice quality can be guaranteed.
*******************************************************************************************/
iAcodecInputVol = 30;
if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iAcodecInputVol))
{
printf("%s: set acodec micin volume failed\n", __FUNCTION__);
return HI_FAILURE;
}
printf("ACODEC_SET_INPUT_VOL vol=%d\n", iAcodecInputVol);
}
close(fdAcodec);
return ret;
}
/******************************************************************************
* function : get frame from Ai, send it to mmzuser
******************************************************************************/
void* SAMPLE_COMM_AUDIO_AiExtMmzUser(void* parg)
{
HI_S32 s32Ret;
HI_S32 AiFd;
SAMPLE_AI2EXTRES_S* pstAiCtl = (SAMPLE_AI2EXTRES_S*)parg;
AUDIO_FRAME_S stFrame;
AEC_FRAME_S stAecFrm;
fd_set read_fds;
struct timeval TimeoutVal;
AI_CHN_PARAM_S stAiChnPara;
char *pPcmData = NULL;
s32Ret = HI_MPI_AI_GetChnParam(pstAiCtl->AiDev, pstAiCtl->AiChn, &stAiChnPara);
if (HI_SUCCESS != s32Ret)
{
printf("%s: Get ai chn[%d] param failed\n", __FUNCTION__, pstAiCtl->AiChn);
return NULL;
}
stAiChnPara.u32UsrFrmDepth = 30;
s32Ret = HI_MPI_AI_SetChnParam(pstAiCtl->AiDev, pstAiCtl->AiChn, &stAiChnPara);
if (HI_SUCCESS != s32Ret)
{
printf("%s: set ai chn param failed\n", __FUNCTION__);
return NULL;
}
FD_ZERO(&read_fds);
AiFd = HI_MPI_AI_GetFd(pstAiCtl->AiDev, pstAiCtl->AiChn);
FD_SET(AiFd, &read_fds);
#define TEST_WRITE_PCM
#ifdef TEST_WRITE_PCM
FILE *fPcmFile = fopen("/sdcard/test.pcm", "w");
if(!fPcmFile) printf("fopen /sdcard/test.pcm error!\n");
#endif
while (pstAiCtl->bStart)
{
TimeoutVal.tv_sec = 1;
TimeoutVal.tv_usec = 0;
FD_ZERO(&read_fds);
FD_SET(AiFd, &read_fds);
s32Ret = select(AiFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
if (s32Ret < 0)
{
break;
}
else if (0 == s32Ret)
{
printf("%s: get ai frame select time out\n", __FUNCTION__);
break;
}
if (FD_ISSET(AiFd, &read_fds))
{
/* get frame from ai chn */
memset(&stAecFrm, 0, sizeof(AEC_FRAME_S));
s32Ret = HI_MPI_AI_GetFrame(pstAiCtl->AiDev, pstAiCtl->AiChn, &stFrame, &stAecFrm, HI_FALSE);
if (HI_SUCCESS != s32Ret )
{
#if 0
printf("%s: HI_MPI_AI_GetFrame(%d, %d), failed with %#x!\n", \
__FUNCTION__, pstAiCtl->AiDev, pstAiCtl->AiChn, s32Ret);
pstAiCtl->bStart = HI_FALSE;
return NULL;
#else
continue;
#endif
}
/* send frame to mmzuser */
if(stFrame.u64VirAddr[0]) pPcmData = (char *)stFrame.u64VirAddr[0];
else if(stFrame.u64VirAddr[1]) pPcmData = (char *)stFrame.u64VirAddr[1];
else pPcmData = NULL;
if(pPcmData)
{
#ifdef TEST_WRITE_PCM
if(fPcmFile) fwrite(pPcmData, stFrame.u32Len, 1, fPcmFile);
#endif
}
/* finally you must release the stream */
s32Ret = HI_MPI_AI_ReleaseFrame(pstAiCtl->AiDev, pstAiCtl->AiChn, &stFrame, &stAecFrm);
if (HI_SUCCESS != s32Ret )
{
printf("%s: HI_MPI_AI_ReleaseFrame(%d, %d), failed with %#x!\n", \
__FUNCTION__, pstAiCtl->AiDev, pstAiCtl->AiChn, s32Ret);
pstAiCtl->bStart = HI_FALSE;
return NULL;
}
}
}
#ifdef TEST_WRITE_PCM
if(fPcmFile)
{
fclose(fPcmFile);
fPcmFile = NULL;
}
#endif
pstAiCtl->bStart = HI_FALSE;
return NULL;
}
海思的sample写得非常好了,一般只要分析下原理图和海思接口文档,调一调音频配置参数就可以了。