海思hi3518ev300说明书_海思3516dv300方案开发

海思hi3518ev300说明书_海思3516dv300方案开发1.硬件内置AudioCodec/外置FM1288,hi3516dv300为内置audiocodec,硬件上外接FM1288,通过MIC单端/差分输入音频.2.重要概念2.1.I2S相关概念(1)LRCLK(帧时钟,也称为WS) 当LRCLK为低电平时表示左声道,高电平时表示右声道, LRCLK的频率=采样频率(2)SCLK(串行时钟),也叫BCLK(位时钟);方波形式存在 对应数字音频的每一位数据,SCLK都有一个脉冲. SCLK的频率=2*采样频率*采样位数

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1.硬件

在这里插入图片描述

Hi3516支持内置AudioCodec/外置音频解码芯片; 由于这里硬件上外接FM1288,故走的是外置,通过I2S接入, 通过MIC单端/差分输入音频.
由于之前一直调试内置Codec,这里任然保留内置相关代码;

2.重要概念

2.1. I2S相关概念

(1)LRCLK (帧时钟,也称为WS)
	当LRCLK为低电平时表示传输左声道,高电平时表示传输右声道,
	LRCLK的频率 = 采样频率

(2)SCLK(串行时钟) ,也叫BCLK(位时钟);方波形式存在
	对应数字音频的每一位数据,SCLK都有一个脉冲.
	SCLK的频率 = 2 * 采样频率 * 采样位数;

 (3) SDATA 串行数据,就是二进制补码表示的音频数据.

(4) MCLK(主时钟,也叫系统时钟)
	一般采样频率的256倍或384倍,它并不是必须的,可有可无,具体看要求.

(5)
	I2S是一种比较简单的数字接口协议,没有地址或设备选择机制;
	在I2S总线上,只能同时存在一个主设备和发送设备;
	主设备可以是发送设备,也可以是接收设备,或是协调发送设备和接收设备的其他控制设备;

2.2 关键点

(1)  底层时序不需要我们自己实现,如i2s如何控制FM1288等.
(2) i2c用的连在主芯片(hi3516dv300)上,就可以直接用底层的驱动.
(3) FM1288的i2s,应该已经封装到mpp里面,只需通过i2c配置好codec,然后通过mpp库操作ai/ao接口即可.
(4) 通过i2c配置下寄存器,一般codec都是配置i2s的模式(主/从,采样率等参数),i2s的bclk,ws等;
(5) 主时钟(MCLK)要看看是有海思做主(master)还是由codec()做主 (slave);
(6) 一般都是由主设备提供MCLK,帧时钟和位时钟都是通过这个MLCK计算出来的.

3.音频上行(ai->aenc)

软件设计上参考: 对应SDK/mpp/sample/audio/sample_audio.c

先配置i2c.通过引脚图及hdmi命令配置:
如:system("himm 0x114F004C 0x103");

据手册: 在 AI/AO 设备主模式下,建议用户先配置好AI/AO,在配置codec;

3.1. 输入初始化

	HI_S32 rc ,i;
AIO_ATTR_S stAioAttr;
AUDIO_DEV   AiDev = 0;
stAioAttr.enSamplerate   = AUDIO_SAMPLE_RATE_8000;
stAioAttr.enBitwidth     = AUDIO_BIT_WIDTH_16;
stAioAttr.enWorkmode     = AIO_MODE_I2S_MASTER;
stAioAttr.enSoundmode    = AUDIO_SOUND_MODE_MONO;
stAioAttr.u32EXFlag      = 1;
stAioAttr.u32FrmNum      = 30;
stAioAttr.u32PtNumPerFrm = 320;
stAioAttr.u32ChnCnt      = 2; //最大只能支持2个
stAioAttr.u32ClkSel      = 1;
//stAioAttr.enI2sType = AIO_I2STYPE_INNERCODEC; 选择内置Codec解码
stAioAttr.enI2sType      = AIO_I2STYPE_EXTERN;//若外部单独有解码芯片,需要选择外部,另需要确认是否支持;
rc = HI_MPI_AI_SetPubAttr(AiDev, &stAioAttr);
//rc错误处理,以下均省略...
rc = HI_MPI_AI_Enable(AiDev);
AI_CHN_PARAM_S pstChnParam;
for(int j = 0; j < stAioAttr.u32ChnCnt; j++)
{ 

rc = HI_MPI_AI_GetChnParam(AiDev, j, &pstChnParam);
pstChnParam.u32UsrFrmDepth = 30;
rc = HI_MPI_AI_SetChnParam(AiDev, j,&pstChnParam);
rc = HI_MPI_AI_EnableChn(AiDev, j);
}  
#if 1 //这部分据实际情况慢慢调
//3516dv300输入不支持 HI_MPI_AI_SetVqeAttr,可用HI_MPI_AI_SetTalkVqeAttr
//声音质量增强功能(Talk)相关属性
AUDIO_DEV AiDevId = 0;
AI_CHN AiChn = 0;
AUDIO_DEV AoDevId = 0;
AO_CHN AoChn = 0;
AI_TALKVQE_CONFIG_S pstVqeConfig;
memset(&pstVqeConfig, 0, sizeof(AI_TALKVQE_CONFIG_S));
pstVqeConfig.u32OpenMask = AI_TALKVQE_MASK_HPF | AI_TALKVQE_MASK_ANR ;//| AI_TALKVQE_MASK_AGC ;
pstVqeConfig.s32WorkSampleRate = AUDIO_SAMPLE_RATE_8000;
pstVqeConfig.s32FrameSample = 320;
pstVqeConfig.enWorkstate = VQE_WORKSTATE_MUSIC ;
//去低频,表现为轰轰不舒适声音
pstVqeConfig.stHpfCfg.bUsrMode = HI_TRUE;
pstVqeConfig.stHpfCfg.enHpfFreq = AUDIO_HPF_FREQ_150;//建议120或150
//回声抵消
pstVqeConfig.stAecCfg.bUsrMode = HI_FALSE;
// pstVqeConfig.stAecCfg.s8CngMode = 1;//舒适噪音模式
// pstVqeConfig.stAecCfg.s8NearAllPassEnergy = 1;//判断是否无光泽传输的远端能量阈值:
// pstVqeConfig.stAecCfg.s8NearCleanSupEnergy = 2;//近端信号强制复位的能量门限:
// pstVqeConfig.stAecCfg.s16DTHnlSortQTh = 16384;
// pstVqeConfig.stAecCfg.s16EchoBandLow = 10;//语音处理band1,低频参数,
// pstVqeConfig.stAecCfg.s16EchoBandHigh = 25;//41;//语音处理band1,高频参数,
// pstVqeConfig.stAecCfg.s16EchoBandLow2 = 28;//47;
// pstVqeConfig.stAecCfg.s16EchoBandHigh2 = 35;//63;
// HI_S16 s16ERLBand[6] = {4, 6, 36, 49, 50, 51};
// HI_S16 s16ERL[7] = {7, 10, 16, 10, 18, 18, 18};
// memcpy(pstVqeConfig.stAecCfg.s16ERLBand,s16ERLBand,sizeof(s16ERLBand));
// memcpy(pstVqeConfig.stAecCfg.s16ERL,s16ERL,sizeof(s16ERL));
// pstVqeConfig.stAecCfg.s16VioceProtectFreqL = 3;
// pstVqeConfig.stAecCfg.s16VioceProtectFreqL1 = 6;
//去除外界噪音
pstVqeConfig.stAnrCfg.bUsrMode = HI_TRUE;
pstVqeConfig.stAnrCfg.s16NrIntensity = 15;//[0~25]越大降噪力度越高,损伤越高.
pstVqeConfig.stAnrCfg.s16NoiseDbThr = 60;//[30~60]越大,检测力度越弱,声音更平滑
pstVqeConfig.stAnrCfg.s8SpProSwitch = 1;//[0/1]是否开启对音乐细节检测,喧闹场景不建议开
//AGC 更多是放大输入源的声音
pstVqeConfig.stAgcCfg.bUsrMode    = HI_FALSE;
#if 0
pstVqeConfig.stAgcCfg.s8TargetLevel = -2;
pstVqeConfig.stAgcCfg.s8NoiseFloor = -40;
pstVqeConfig.stAgcCfg.s8MaxGain = 30;
pstVqeConfig.stAgcCfg.s8AdjustSpeed = 10;
pstVqeConfig.stAgcCfg.s8ImproveSNR = 2;//上限6db
pstVqeConfig.stAgcCfg.s8UseHighPassFilt = 3;
pstVqeConfig.stAgcCfg.s8OutputMode = 0;
pstVqeConfig.stAgcCfg.s16NoiseSupSwitch = 1;//开启噪声抑制
#endif
//遇到库找不到请看下面
rc = HI_MPI_AI_SetTalkVqeAttr(AiDevId, AiChn, AoDevId, AoChn,&pstVqeConfig);
rc = HI_MPI_AI_EnableVqe(AiDevId, AiChn);
#endif

3.2. 输出初始化

	HI_S32 rc ,i;
HI_S32 s32AoChnCnt; 
AIO_ATTR_S stAioAttr;
AUDIO_DEV   AoDev = 0;
rc = HI_MPI_AO_Disable(AoDev );//先禁用AO设备
stAioAttr.enSamplerate   = AUDIO_SAMPLE_RATE_8000;
stAioAttr.enBitwidth     = AUDIO_BIT_WIDTH_16;
stAioAttr.enWorkmode     = AIO_MODE_I2S_MASTER;
stAioAttr.enSoundmode    = AUDIO_SOUND_MODE_MONO;
stAioAttr.u32EXFlag      = 1;
stAioAttr.u32FrmNum      = 30;
stAioAttr.u32PtNumPerFrm = 320;
stAioAttr.u32ChnCnt      = 2;
stAioAttr.u32ClkSel      = 1;
//stAioAttr.enI2sType = AIO_I2STYPE_INNERCODEC;
stAioAttr.enI2sType      = AIO_I2STYPE_EXTERN;//若外部单独有解码芯片,需要选择外部,另需要确认是否支持;
rc = HI_MPI_AO_SetPubAttr(AoDev , &stAioAttr);
rc = HI_MPI_AO_Enable(AoDev );
/* enable AO channle */
s32AoChnCnt = stAioAttr.u32ChnCnt;
for (i = 0; i < s32AoChnCnt >> stAioAttr.enSoundmode; i++)
{ 

rc = HI_MPI_AO_EnableChn(AoDev , i);
}
#if 0 //没用到
AUDIO_DEV AoDevId = 0;
AO_CHN AoChn = 0;
AO_VQE_CONFIG_S pstVqeConfig;
memset(&pstVqeConfig, 0, sizeof(AO_VQE_CONFIG_S));
pstVqeConfig.u32OpenMask = AO_VQE_MASK_HPF | AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
pstVqeConfig.s32WorkSampleRate = AUDIO_SAMPLE_RATE_8000;
pstVqeConfig.s32FrameSample = 320;
pstVqeConfig.enWorkstate = VQE_WORKSTATE_COMMON ;
//高通滤波功能相关配置
pstVqeConfig.stHpfCfg.bUsrMode = HI_TRUE;
pstVqeConfig.stHpfCfg.enHpfFreq = AUDIO_HPF_FREQ_150;
//去噪
pstVqeConfig.stAnrCfg.bUsrMode = HI_TRUE;//用户模式
pstVqeConfig.stAnrCfg.s16NrIntensity = 15;//[0~25]越大降噪力度越高,损伤越高.
pstVqeConfig.stAnrCfg.s16NoiseDbThr = 60;//[30~60]越大,检测力度越弱,声音更平滑
pstVqeConfig.stAnrCfg.s8SpProSwitch = 1;//[0/1]是否开启对音乐细节检测,喧闹场景不建议开
//自动增益控制
pstVqeConfig.stAgcCfg.bUsrMode    = HI_TRUE;
pstVqeConfig.stAgcCfg.s8TargetLevel = -2;
pstVqeConfig.stAgcCfg.s8NoiseFloor = -20;
pstVqeConfig.stAgcCfg.s8MaxGain = 30;
pstVqeConfig.stAgcCfg.s8AdjustSpeed = 10;
pstVqeConfig.stAgcCfg.s8ImproveSNR = 0;//上限6db
pstVqeConfig.stAgcCfg.s8UseHighPassFilt = 0;
pstVqeConfig.stAgcCfg.s8OutputMode = 0;
pstVqeConfig.stAgcCfg.s16NoiseSupSwitch = 1;//开启噪声抑制
rc = HI_MPI_AO_SetVqeAttr(AoDevId, AoChn, &pstVqeConfig);
rc = HI_MPI_AO_EnableVqe(AoDevId, AoChn);
printf("HI_MPI_AO_EnableVqe AoDevId[%d] rc[%d] \n",AoDevId,rc);
#endif

3.3. codec配置

如果是外置解码芯片,这里不需要配置内部Codec; 外置解码芯片就相当于codec;
应该不需要配置这么多,视情况而定!
	//func(enSamplerate) enSamplerate传进来
HI_S32 fdAcodec= -1;
HI_S32 ret = HI_SUCCESS;
ACODEC_FS_E i2s_fs_sel;   
switch (enSamplerate)
{ 

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_48000:
i2s_fs_sel = ACODEC_FS_48000;
break;
default:
i2s_fs_sel = ACODEC_FS_8000;
break;
}
fdAcodec = open("/dev/acodec",O_RDWR);
if(fdAcodec < 0)
{ 

printf("[%s %d] open dev/acodec failed!\n",__FUNCTION__,__LINE__);
return HI_FALSE;
}
//将内置Codec恢复为默认设置
if(ioctl(fdAcodec, ACODEC_SOFT_RESET_CTRL))
{ 

printf("reset the audio code to the default config error\n");
}
//设置I2s1采样率
if(ioctl(fdAcodec, ACODEC_SET_I2S1_FS, &i2s_fs_sel))
{ 

printf("[%s %d] set i2s1 fs failed!\n",__FUNCTION__,__LINE__);
return HI_FALSE;
}
//输入方式选择
ACODEC_MIXER_E input_mode = ACODEC_MIXER_IN1;//单端输入 ACODEC_MIXER_IN_D;//:差分
if (ioctl(fdAcodec, ACODEC_SET_MIXER_MIC, &input_mode))
{ 

printf("%s: select acodec input_mode failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
int iVol = 50;//[-78-80] 建议[19-50]
#if 1
//输入音量之PGA模块
if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
{ 

printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
return HI_FALSE;
}
unsigned int gain_mac;
gain_mac = 15;//15为最大增益30db 16:-1.5db
if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICL, &gain_mac))
{ 

printf("%s: ioctl ACODEC_SET_GAIN_MICL failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
if (ioctl(fdAcodec, ACODEC_SET_GAIN_MICR, &gain_mac))
{ 

printf("%s: ioctl ACODEC_SET_GAIN_MICR failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
//输入音量之BOOST模块
if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
{ 

printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
return HI_FALSE;
}
unsigned int enable_boostl;
enable_boostl = 0x1;//取1时模拟增益增加20db
if (ioctl(fdAcodec, ACODEC_ENABLE_BOOSTL, &enable_boostl))
{ 

printf("%s: ioctl ACODEC_ENABLE_BOOSTL failed\n", __FUNCTION__);
return HI_FALSE;
}
unsigned int enable_boostr;
enable_boostr = 0x1;//取1时模拟增益增加20db
if (ioctl(fdAcodec, ACODEC_ENABLE_BOOSTR, &enable_boostr))
{ 

printf("%s: ioctl ACODEC_ENABLE_BOOSTR failed\n", __FUNCTION__);
return HI_FALSE;
}
//#else
//输入音量之ADC模块
if (ioctl(fdAcodec, ACODEC_SET_INPUT_VOL, &iVol))
{ 

printf("%s: ioctl ACODEC_SET_INPUT_VOL failed\n", __FUNCTION__);
return HI_FALSE;
}
ACODEC_VOL_CTRL vol_ctrl;
vol_ctrl.vol_ctrl_mute = 0;//不静音
vol_ctrl.vol_ctrl = 0;//[0~127] 0音量最大
//左声道输入音量控制
if(ioctl(fdAcodec, ACODEC_SET_ADCL_VOL, &vol_ctrl))
{ 

printf("%s: acodec set adcl vol failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
if(ioctl(fdAcodec, ACODEC_SET_ADCR_VOL, &vol_ctrl))
{ 

printf("%s: acodec set adcr vol failed\n", __FUNCTION__);
ret = HI_FAILURE;
}
#endif
//输出总音量控制
iVol = 4; //[-126~6]
if (ioctl(fdAcodec, ACODEC_SET_OUTPUT_VOL, &iVol))
{ 

printf("[%s %d] set output vol fs failed!\n",__FUNCTION__,__LINE__);
}
//把MICIN静音(MUTE)功能关闭
#if 1
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;
}
#endif
close(fdAcodec);

4.音频下行 (adec->ao)

一般情况上行没问题,下行只是方向相反而已!
伪代码:

	HI_MPI_ADEC_CreateChn(chn,&解码参数)HI_MPI_SYS_Bind(HI_ID_ADEC,..HI_ID_AO);
while(获取流)
{ 

HI_MPI_ADEC_SendStream(chn,&码流结构体,阻塞否?);
}

5.遇到的问题

问题1:
HI3516DV300 HI_MPI_AI_EnableVqe调节音频使能Vqe时出现.
dlopen libhive_common.so/libsecurec.so or libhive_AEC.so failed
解决方案: 
在sdk中找到对应的.so文件,放到 usr/lib 下并记得改权限(重要).
问题2:
下行过程遇到的问题:HI_MPI_ADEC_SendStream 0xA0188040(码流错误);
排查过程:
1> 初步怀疑解码参数问题,检查后排除;可以在send_stream前面将下行码流保存成对应格式,如.g711a格式,在pc上播放;首先确保码流到这里能播放;
2> 第一步能通过,那么试试自编自解是否可行(首先确保上行ok,音频功放ok),在上行前先创建解码通道并绑定ao,在HI_MPI_AENC_GetStream获取流后立马又发给ao;
3> 第二步基本都没问题,记录下发送成功的字节长度;最终将问题定位到海思头(一定确保上行码流长度和下行码流长度一致)
如上行324字节(320+4字节海思头),下行也要保证一样,多了少了可能就有问题!!!

6.fm1288芯片

  1. 首先,向厂家要一份linux的驱动参考代码,方便参考配置;
  2. fm1288芯片使能的标志是MIC_BIAS引脚输出高电平;
  3. PWD# 引脚需要上电, RST#引脚需要复位在拉高,且需要在其后的90ms的软件初始化;
  4. I2S类型需选择AIO_I2STYPE_EXTERN才能通过I2C配置成功,不然一直显示超时;
  5. 参考 https://blog.csdn.net/qq_37565330/article/details/79460692

7.总结

多看手册,一般手册上都能找到答案.
结合sdk示例.
若软件上没啥问题,可适当排查硬件.硬件时钟,与示波器结合.分析时序等等一步步排查;

参考:https://baike.baidu.com/item/I2S/3443390?fr=aladdin

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190250.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • C语言实现学生成绩管理系统设计

    C语言实现学生成绩管理系统设计本系统有**增加学生记录、修改学生记录、删除学生记录、按姓名查询学生记录、按C语言成绩对学生进行排序、退出系统**6大功能。能够对学生的姓名,学号,c语言成绩做相应的操作。在检测到输入成绩大于55时,会自动加上5。该管理系统设计功能模块图:下面是源代码:#include”stdio.h”#include”string”/*定义学生结构体*/structStudent

  • easyui textbox 密码框的prompt提示语显示*号问题的解决办法

    easyui textbox 密码框的prompt提示语显示*号问题的解决办法easyuitextbox密码框的prompt提示语显示*号问题的解决办法

  • 使用eclipse创建java项目「建议收藏」

    使用eclipse创建java项目「建议收藏」注意:安装前必备环境:安装eclipse之前必须安装JDK环境。安装方法主要有:下载JDK,安装JDK,配置JDK的环境变量,测设JDK是否安装好。具体步骤详见博文: java开发环境搭建 使用eclipse从头一步步创建java项目1.下载eclipse官网地址:http://www.eclipse.org/downloads/下载EclipseIDEforJava

  • h5播放rtsp流_h5页面嵌入微信公众号

    h5播放rtsp流_h5页面嵌入微信公众号项目需求最近遇到一个新需求,将rtsp视频流接入h5页面中,rtsp是无法直接在h5页面上显示的,所以得通过一些手段将视频转成可以在h5上显示的格式;博主尝试过用nginx+ffmpeg转流,也尝试过用bilibili开源的flv.js转流;但最终效果都不太好,延迟高,卡顿时间长;后面发现一个神器VLC客户端,实时播放,完全不卡顿。前期准备VLC下载链接根据上方链接下载VLC客户端,根据自己的操作系统下载安装,博主使用的是windows10系统实际开发1.确保rtsp视频流可用,海康威视IP

  • android手机指纹识别_屏下指纹缺点

    android手机指纹识别_屏下指纹缺点手机科技发展到目前阶段,对于指纹解锁技术已经到第二阶段了,第一阶段有三种指纹解锁方式:正面、侧面、背面,而第二阶段那就是目前还处于上阵新兵状态的屏下指纹,这里我就我个人使用的情况,来谈一下这几种指纹解锁的优劣势吧。一、正面指纹解锁,代表机型iPhone如果我没有记错的话,虽然不是第一个用,但苹果的指纹解锁是从iPhone5S开始,并流行起来的,并且从此就一发不可收拾,我是从iPhone6SP开…

  • spring任务调度scheduled_golang 任务调度

    spring任务调度scheduled_golang 任务调度1、任务调度接口TaskScheduler提供了多种方法来调度将来某个时间点要运行的任务。2、触发器Trigger实现PeriodicTrigger和CronTrigger。3、@Scheduled注解创建定时任务4、@Async注解异步方法执行,value属性指定任务执行器。5、task:scheduler、task:executor创建调度器和执行器…

    2022年10月11日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号