海思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)


相关推荐

  • plsql激活码(永久可用)

    plsql激活码(永久可用)12.07版本的:产品编号ProductCode:kfj6yg6rfyhqcha6cbgs6fsw3kyje7a6qr序列号SerialNumber:276182口令Password:xs374ca

  • SQL Server中的GUID

    GUID(Globaluniqueidentifier)全局唯一标识符,它是由网卡上的标识数字(每个网卡都有唯一的标识号)以及CPU时钟的唯一数字生成的的一个16字节的二进制值。GUID

    2021年12月22日
  • TI ADI DSP 与 ARM Cortex-A 的 FIR FFT 性能对比

    TI ADI DSP 与 ARM Cortex-A 的 FIR FFT 性能对比DSP作为计算密集型的芯片,一度是FIR和FFT运算的主力芯片,而TI和ADI两大DSP芯片公司推出的DSP产品也互不相让。可以预见,随着ARM的广泛使用和性能的提高,DSP作为独立的芯片,应用场景会越来越少,也许会慢慢退出历史的舞台;而数字信号处理,会以DSPIP软核或者硬核的形式,出现在各种芯片当中。摩尔定律和制造工艺的发展,推动着芯片行业飞速前进,不进则退。

    2022年10月14日
  • HTML 5 Web 存储

    HTML5提供了两种在客户端存储数据的新方法:localStorage-没有时间限制的数据存储sessionStorage-针对一个session的数据存储html5webstora

    2021年12月25日
  • nodejs安装淘宝镜像(配置淘宝镜像)

    强烈推荐30个原生JavaScript的demo,包括canvas时钟特效、自定义视频播放器、搜索栏快速匹配、fetch访问资源、console调试技巧等,先fork后学习,详见点击打开链接,欢迎点赞~~~谢谢,共同进步学习!将npm的注册表源设置为国内的镜像1、国内用户,建议将npm的注册表源设置为国内的镜像,可以大幅提升安装速度2、国内优秀npm镜像推荐及使用:http://rin…

  • Laravel框架_php laravel框架

    Laravel框架_php laravel框架laravel框架一、laravel简介laravel是一套优雅简介的PHP开发框架,受欢迎程度非常之高,功能强大,工具齐全;https://www.jianshu.com/p/206592c78113二、简单介绍1、laravel是基于mvc模式的php框架,m——模型层,v——视图层,c——控制器层;以下为laravel框架的目录文件,框出来的文件目录将在后续中用到:2、什么是MV…

    2022年10月22日

发表回复

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

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