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 0pstVqeConfig.stAgcCfg.s8TargetLevel = -2;pstVqeConfig.stAgcCfg.s8NoiseFloor = -40;pstVqeConfig.stAgcCfg.s8MaxGain = 30;pstVqeConfig.stAgcCfg.s8AdjustSpeed = 10;pstVqeConfig.stAgcCfg.s8ImproveSNR = 2;//上限6dbpstVqeConfig.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;//上限6dbpstVqeConfig.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.5dbif (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时模拟增益增加20dbif (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时模拟增益增加20dbif (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 1HI_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;}
#endifclose(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 下并记得改权限(重要).具体看: https://blog.csdn.net/qq_39048131/article/details/121848761问题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

海思hi3516dv300音频调节总结相关推荐

  1. 52-20210322华为海思Hi3516DV300的linux系统编译(eMMC模式)1

    52-20210322华为海思Hi3516DV300的linux系统编译(eMMC模式) 2021/3/22 18:00 请严重注意: 本文所使用的的SDK是:Hi3516CV500R001C02SP ...

  2. 51-20210316华为海思Hi3516DV300的linux系统编译1(SPI模式)

    51-20210316华为海思Hi3516DV300的linux系统编译 2021/3/16 10:42 https://xueqiu.com/7970718062/159110439 官井想开挖掘机 ...

  3. 07-20210305在WIN10下通过USB口给华为海思Hi3516DV300刷机(鸿蒙系统)

    07-20210305在WIN10下通过USB口给华为海思Hi3516DV300刷机(鸿蒙系统) 2021/3/5 17:26 https://blog.csdn.net/cocoron/articl ...

  4. 08-20210305在WIN10下通过网口给华为海思Hi3516DV300刷机(鸿蒙系统)

    08-20210301在WIN10下通过网口给华为海思Hi3516DV300刷机(鸿蒙系统) 2021/3/5 11:03 https://bbs.elecfans.com/jishu_2002000 ...

  5. 51-20210316华为海思Hi3516DV300的linux系统编译2(SPI模式)

    51-20210316华为海思Hi3516DV300的linux系统编译 2021/3/16 10:42 https://xueqiu.com/7970718062/159110439 官井想开挖掘机 ...

  6. 在WIN10下通过网口给华为海思Hi3516DV300刷机(鸿蒙系统)

    08-20210301在WIN10下通过网口给华为海思Hi3516DV300刷机(鸿蒙系统) 2021/3/5 11:03 https://bbs.elecfans.com/jishu_2002000 ...

  7. 56-20210402华为海思Hi3516DV300的linux系统下读取TF卡(eMMC模式)

    56-20210402华为海思Hi3516DV300的linux系统下读取TF卡(eMMC模式) 2021/4/2 15:02 https://xueqiu.com/7970718062/159110 ...

  8. 海思Hi3516DV300软硬件全套开发资料

    海思Hi3516DV300软硬件全套开发资料 海思Hi3516DV300软硬件全套开发资料:https://pan.baidu.com/s/1O1TnELnM2FgZD2Dl82wG7g 提取码: k ...

  9. 61-20210407华为海思Hi3516DV300的linux系统下控制GPIO口(标准linux模式点亮LED灯)

    61-20210407华为海思Hi3516DV300的linux系统下控制GPIO口(标准linux模式点亮LED灯) 2021/4/7 15:13 https://xueqiu.com/797071 ...

最新文章

  1. FaceShifter:一秒换脸的人脸交换模型
  2. mariadb 基础使用
  3. C++从0到1的入门级教学(二)——数据类型
  4. UBUNTU下面安装ICE失败记录过程
  5. 探秘手淘高可用平台(三)——热修复和开发流程
  6. 23. Navigator javaEnabled() 方法
  7. 2021-09-03101. 对称二叉树
  8. javascript 小白学习指南专题 this
  9. 意外找回CSDN老账号,记录记录新账号备忘
  10. 启动不了 驱动程序签字功能,bios关闭驱动数字签名 如何在bios禁用驱动程序签名,装系统,启动行为那个无效?...
  11. 字节跳动的 8 轮视频面试流程
  12. 恢复计算机注册表命令,恢复电脑注册表的方法
  13. win7托盘区没有蓝牙图标
  14. LUK-Triumphal arch
  15. cnzz统计代码被谷歌浏览器拦截警告
  16. ndo2db: mysql_error: ‘Unknown column ‘importance’ in ‘field list”
  17. C语言/C++基础之五彩炫酷珠
  18. Java中split的用法,分割String字符串
  19. 华为OD机试真题2023(JavaScript)
  20. ChinaNet无线接入后,浏览器自动跳转到登陆界面的原理

热门文章

  1. 蓝牙HC05模块,AT其他指令爆出ERROR[0] 解决方法
  2. 安科瑞数据中心行业电能质量监测与治理方案-李亚俊
  3. telnet不是内部或外部命令怎么办
  4. HTML显示磁盘容量,导致:IOError:[Errno 28]设备上没有剩余空间:磁盘上有很多空间的’../results/32766.html’...
  5. 防火墙入侵与检测 day03 详解NAT及配置
  6. 王爽 《汇编语言》之寄存器
  7. Android使用MediaCodec和OpenGL对多段视频画面进行裁剪和拼接
  8. 闲置台式机+文件服务器,闲置电脑打造NAS:安装群晖NAS系统
  9. 批量付款到户接口,批量转账接口
  10. 三星笔记本bios设置里找不到U盘启动盘的解决方法