海思HISI 3518EV200 AEC回音消除+ANR语音降噪

问题描述:

HISI 3518EV200 平台开发的IPC产品,其中具有对讲功能,能和手机APP端进行全双工双向对讲,但全双工的时候碰到一个问题,就是会产生回音,当人在手机APP端说话时,往往能听到设备端回回来的回音(设备端喇叭播放的声音经过MIC又传回手机端)。

 

解决方法:

  1. 外接回音消除芯片+电路的方法,但从成本的角度来说该方法会增加几块钱的成本(被放弃)。
  2. 利用海思自带的AEC回音抵消功能,来消除回音,能节省成本(采用该方法)。

实际情况:

AEC采用默认的参数设置,发现全双工语音对讲仍然有回音,虽然听不

出回音的内容,但能确定是自己说话的回过来的声音。

 

方法详解(本文都是针对方法2来展开的):

  1. AEC回音抵消:

         依据HISI开发文档:

  • AEC功能 介绍:

与其他功能模块只需要 Sin 数据不同, AEC 模块需要 Sin(Signal In)和 Rin

(Reference In)两路数据来进行算法处理,最终得到处理后的 sou(Signal Out)数据。

其中, Sin 为加入了回声的近端输入, Rin 为参考帧(回声)数据。成功启用回声抵消

需要具备一定条件:单声道模式,工作采样率为 8kHz、 16kHz,且 MIC 采集语音数据

的 AI 帧长和远程语音播放的 AO 配置帧长必须相同。以上条件 AI 和 AO 都必须满

足。

以上标红部分为HISI开发文档注明开启AEC功能需要满足的条件。需自行满足。

所以代码中,AEC 和 ANR 功能都放到AI AO初始化的部分来做了(ANR语音降噪功能在做

AEC功能时顺便就做了ANR)。

 

  • 再看AEC的相关参数配置数据结构(其中每一项的详细介绍见HISI文档):
typedef struct hiAI_AEC_CONFIG_S
{
    HI_BOOL bUsrMode;
    HI_S8 s8CngMode; /* cosy-noisy mode:0 close,1 open, default 1*/
    HI_S8 s8NearAllPassEnergy;
    HI_S8 s8NearCleanSupEnergy;
    HI_S16 s16DTHnlSortQTh;
    HI_S16 s16EchoBandLow;
    HI_S16 s16EchoBandHigh;
    HI_S16 s16EchoBandLow2;
    HI_S16 s16EchoBandHigh2;
    HI_S16 s16ERLBand[6];
    HI_S16 s16ERL[7];
    HI_S16 s16VioceProtectFreqL;
    HI_S16 s16VioceProtectFreqL1;
    HI_S32 s32Reserved;
} AI_AEC_CONFIG_S;

 

关于该数据结构,其中有几点注意的,HISI完档中提到了 :

【注意事项】

  • 当用户模式开启时,其他参数才生效,否则按照 AI_VQE_CONFIG_S/AI_TALKVQE_CONFIG_S 中的工作模式 enWorkstate 对应的默认值来配置。
  • 配置参数时,只有在用户模式开启时,才会对高级参数做正确性检查,只有正确的高级参数才能配置成功。

【相关数据类型及接口】

AI_VQE_CONFIG_S

 

在完成AEC功能的添加,采用默认的参数设置后,发现全双工语音对讲仍然有回音(虽然听不出回音的内容,但能确定是自己说话的回过来的声音)。后来经过调整“语音处理频段”的高低频参数范围来达到了消除回音的效果:

stAiVqeAttr.stAecCfg.s16EchoBandLow = 10; //default:10

stAiVqeAttr.stAecCfg.s16EchoBandHigh = 25; //default:41

stAiVqeAttr.stAecCfg.s16EchoBandLow2 = 28; //default:47

stAiVqeAttr.stAecCfg.s16EchoBandHigh2 = 35; //default:63

 

 

附上代码:

AI部分:

/*****************************************************************************
函数名称:StartAudioAI
函数功能:开启输入,单通道chid  --1
输入参数:无
输出参数:无
返   回    值:无
使用说明: 内部调用

******************************************************************************/
 
int Audio::StartAudioAI()
{
     
    HI_S32  s32Ret;
    AUDIO_DEV AiDevId = 0;   
    AI_CHN AiChn = 0;
    s32Ret = HI_MPI_AI_SetPubAttr(AiDevId, &m_stAioAttr);
    if (s32Ret)
    {
        printf("%s: HI_MPI_AI_SetPubAttr(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
        return HI_FAILURE;
    }
    if (HI_MPI_AI_Enable(AiDevId))
    {
        printf("%s: HI_MPI_AI_Enable(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
        return HI_FAILURE;
    }                
 
    if (HI_MPI_AI_EnableChn(AiDevId, AiChn))
    {
        printf("%s: HI_MPI_AI_EnableChn(%d,%d) failed with %#x\n", __FUNCTION__,\
                AiDevId, AiChn, s32Ret);
        return HI_FAILURE;
    }
#if 1
    HI_S16 s16ERLBand[6] = {4,6,36,49,50,51};
    HI_S16 s16ERL[7] = {7,10,16,10,18,18,18};
    #define SAMPLE_AUDIO_PTNUMPERFRM   160
     
    AI_VQE_CONFIG_S stAiVqeAttr;   
    stAiVqeAttr.s32WorkSampleRate    = AUDIO_SAMPLE_RATE_8000;
    stAiVqeAttr.s32FrameSample       = SAMPLE_AUDIO_PTNUMPERFRM;
    stAiVqeAttr.enWorkstate          = VQE_WORKSTATE_COMMON;
     
    //AEC回音消除
    printf("********init AEC******* \n");
    stAiVqeAttr.bAecOpen             = HI_TRUE;
    stAiVqeAttr.stAecCfg.bUsrMode    = HI_TRUE;
    stAiVqeAttr.stAecCfg.s8CngMode   = 0;
    #if 1
   stAiVqeAttr.stAecCfg.s8NearAllPassEnergy = 1; //default:1
   stAiVqeAttr.stAecCfg.s8NearCleanSupEnergy = 2;   //default:2
   stAiVqeAttr.stAecCfg.s16DTHnlSortQTh = 16384;    //default:16384
   stAiVqeAttr.stAecCfg.s16EchoBandLow = 10;     //default:10
   stAiVqeAttr.stAecCfg.s16EchoBandHigh = 25;        //default:41
   stAiVqeAttr.stAecCfg.s16EchoBandLow2 = 28;        //default:47
   stAiVqeAttr.stAecCfg.s16EchoBandHigh2 = 35;       //default:63
   memcpy(&stAiVqeAttr.stAecCfg.s16ERLBand,&s16ERLBand,sizeof(s16ERLBand));//default
    memcpy(&stAiVqeAttr.stAecCfg.s16ERL,&s16ERL,sizeof(s16ERL));//default
   stAiVqeAttr.stAecCfg.s16VioceProtectFreqL = 3;   //default
   stAiVqeAttr.stAecCfg.s16VioceProtectFreqL1 = 6; //default
    #endif
     
     
    stAiVqeAttr.bAgcOpen             = HI_TRUE;
    stAiVqeAttr.stAgcCfg.bUsrMode    = HI_FALSE;
 
    //ANR语音降噪
    stAiVqeAttr.bAnrOpen             = HI_TRUE;
    #if 1
    stAiVqeAttr.stAnrCfg.bUsrMode = HI_TRUE;
    stAiVqeAttr.stAnrCfg.s16NrIntensity = 25; //降噪力度配置,取值为[0, 25]
    stAiVqeAttr.stAnrCfg.s16NoiseDbThr = 60;  //噪声门限配置,取值为[30,60],配置值越大,检测力度越弱,声音更平滑
    stAiVqeAttr.stAnrCfg.s8SpProSwitch = 0;       //音乐检测开关,取值为[0,1]
    #endif
 
    stAiVqeAttr.bHpfOpen             = HI_TRUE;
    stAiVqeAttr.stHpfCfg.bUsrMode    = HI_TRUE;
    stAiVqeAttr.stHpfCfg.enHpfFreq   = AUDIO_HPF_FREQ_150;
     
    stAiVqeAttr.bRnrOpen             = HI_FALSE;
    stAiVqeAttr.bEqOpen              = HI_FALSE;
    stAiVqeAttr.bHdrOpen             = HI_FALSE;      
 
    #define SAMPLE_AUDIO_AO_DEV 0
    AO_CHN AoChn = 0;
     
 
    s32Ret = HI_MPI_AI_SetVqeAttr(AiDevId, AiChn, SAMPLE_AUDIO_AO_DEV, AoChn, &stAiVqeAttr);  
    if (s32Ret)
    {
        printf("%s: HI_MPI_AI_SetVqeAttr(%d) failed with %#x\n", __FUNCTION__, AiDevId, s32Ret);
        return HI_FAILURE;
    }
 
    s32Ret = HI_MPI_AI_EnableVqe(AiDevId, AiChn);
    if (s32Ret)
    {
        printf("%s: HI_MPI_AI_EnableVqe(%d,%d) failed with %#x\n", __FUNCTION__, AiDevId, AiChn, s32Ret);
        return s32Ret;
    }   
#endif
    HI_MPI_AI_EnableChn(AiDevId, 1);
    return HI_SUCCESS;
}

AO部分:

 

/*****************************************************************************
函数名称:StartAudioAO
函数功能:开启输出,双声道
输入参数:无
输出参数:无
返   回    值:无
使用说明: 内部调用
 
******************************************************************************/
 
int Audio::StartAudioAO()
{
     
    HI_S32 s32Ret;
    AUDIO_DEV AoDevId =0;
    AO_CHN AoChn=0;
    ADEC_CHN AdChn=0 ;
    AIO_ATTR_S AioAttr;
    memset(&AioAttr,0x0,sizeof(AIO_ATTR_S));
    memcpy(&AioAttr,&m_stAioAttr,sizeof(AIO_ATTR_S));
    AioAttr.u32PtNumPerFrm = NumPerFrm;
    AioAttr.enBitwidth = AUDIO_BIT_WIDTH_16;
     
//  AIO_ATTR_S *pstAioAttr = &AioAttr;
//  AIO_ATTR_S *pstAioAttr = &m_stAioAttr;
    s32Ret = HI_MPI_AO_SetPubAttr(AoDevId, &AioAttr);
    if(HI_SUCCESS != s32Ret)
    {
        printf("%s: HI_MPI_AO_SetPubAttr(%d) failed with %#x!\n", __FUNCTION__, \
               AoDevId,s32Ret);
        return HI_FAILURE;
    }
    s32Ret = HI_MPI_AO_Enable(AoDevId);
    if(HI_SUCCESS != s32Ret)
    {
        printf("%s: HI_MPI_AO_Enable(%d) failed with %#x!\n", __FUNCTION__, \
               AoDevId, s32Ret);
        return HI_FAILURE;
    }
    MPP_CHN_S stSrcChn,stDestChn;
    AdChn = 0;
    for(unsigned int i=0;i< 1;i++)
    {
        AoChn = i;        
        stSrcChn.enModId = HI_ID_ADEC;
        stSrcChn.s32DevId = 0;
        stSrcChn.s32ChnId = AdChn;
        stDestChn.enModId = HI_ID_AO;
        stDestChn.s32DevId = AoDevId;
        stDestChn.s32ChnId = AoChn;  
        s32Ret = HI_MPI_AO_EnableChn(AoDevId, AoChn);
        if(HI_SUCCESS != s32Ret)
        {
            printf("%s: HI_MPI_AO_EnableChn(%d) failed with %#x!\n", __FUNCTION__,\
                   AoChn, s32Ret);
            return HI_FAILURE;
        }
#if 1
        #define SAMPLE_AUDIO_PTNUMPERFRM 160
        AO_VQE_CONFIG_S stAoVqeAttr;
        memset(&stAoVqeAttr, 0, sizeof(AO_VQE_CONFIG_S));
         
        stAoVqeAttr.bEqOpen            = HI_TRUE;
        stAoVqeAttr.s32WorkSampleRate    = AUDIO_SAMPLE_RATE_8000;
        stAoVqeAttr.s32FrameSample       = SAMPLE_AUDIO_PTNUMPERFRM;
        stAoVqeAttr.enWorkstate          = VQE_WORKSTATE_COMMON;
         
        stAoVqeAttr.bAgcOpen             = HI_TRUE;
        stAoVqeAttr.stAgcCfg.bUsrMode    = HI_FALSE;
         
        stAoVqeAttr.bAnrOpen            = HI_TRUE;
        #if 1
        stAiVqeAttr.stAnrCfg.bUsrMode = HI_TRUE;
        stAiVqeAttr.stAnrCfg.s16NrIntensity = 25;//降噪力度配置,取值为[0, 25]
        stAiVqeAttr.stAnrCfg.s16NoiseDbThr = 60;//噪声门限配置,取值为[30,60],配置值越大,检测力度越弱,声音更平滑
        stAiVqeAttr.stAnrCfg.s8SpProSwitch = 0;//音乐检测开关,取值为[0,1]
        #endif
         
        stAoVqeAttr.bHpfOpen            = HI_TRUE;
        stAoVqeAttr.stHpfCfg.bUsrMode    = HI_TRUE;
        stAoVqeAttr.stHpfCfg.enHpfFreq   = AUDIO_HPF_FREQ_150;
 
        stAoVqeAttr.bEqOpen = HI_FALSE;
         
 
 
         
        s32Ret = HI_MPI_AO_SetVqeAttr(AoDevId, i, &stAoVqeAttr);
        if(HI_SUCCESS != s32Ret)
        {
            printf("line %d: HI_MPI_AO_SetVqeAttr(%d) failed with %#x!\n", __LINE__,\
                   AoChn, s32Ret);
            return HI_FAILURE;
        }
 
        s32Ret = HI_MPI_AO_EnableVqe(AoDevId, i);
        if (s32Ret)
        {
            printf("%s: HI_MPI_AO_EnableVqe(%d,%d) failed with %#x\n", __FUNCTION__, AoDevId, i, s32Ret);
            return s32Ret;
        }
                 
#endif  
        s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn); 
        if(HI_SUCCESS != s32Ret)
        {
            printf("line %d: HI_MPI_SYS_Bind(%d) failed with %#x!\n", __LINE__,\
                   AoChn, s32Ret);
            return HI_FAILURE;
        }
    }
     
 
 
    return HI_SUCCESS;
}

实际调试效果还得以实际设备为准,不同设备不同的电路,会有不一样的噪声干扰等,会导致参数不一样。

 

 

 

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: hisi16ev200 bt1120是一种多媒体处理器芯片。该芯片由海思半导体公司设计和生产,是一种专为多媒体应用而开发的高性能处理器。 hisi16ev200 bt1120采用了先进的制程技术和架构设计,拥有强大的处理能力和丰富的接口功能。它支持多种多媒体格式的解码和编码,可以处理高清视频和音频数据,并提供了高品质的图像和声音输出。 同时,hisi16ev200 bt1120还具备丰富的接口资源,包括多个USB接口、以太网接口、外设接口等,方便用户与其他设备进行数据传输和交互。 此外,hisi16ev200 bt1120还具备低功耗特性,能够提供高效能的同时减少能耗,具有较好的节能性能。 总的来说,hisi16ev200 bt1120是一款功能强大、性能高效的多媒体处理器芯片,广泛应用于数字电视、机顶盒、网络摄像头、智能手机等多媒体设备中,为用户提供优质的多媒体体验。 ### 回答2: hisi16ev200是一款由海思公司开发的嵌入式处理器,它是一款高性能的芯片,广泛应用于视频处理、智能家居、机器人等领域。hisi16ev200采用了先进的16nm工艺制造,具备了较高的计算性能和低功耗。 bt1120是一种视频传输接口标准,常用于电视、监控、摄像机等设备中。它支持标清视频信号传输,具备较低的传输延迟和较高的传输带宽。 hisi16ev200与bt1120之间存在着一定的关系。首先,hisi16ev200芯片具备强大的视频处理能力,可以对从bt1120接口传来的视频信号进行处理和编码,提供优质的视频输出。 其次,hisi16ev200还支持多种其他视频传输接口,如HDMI、LVDS等,可以与bt1120接口进行转换或者同时使用,提供更多的接口选择。 此外,hisi16ev200还可以与其他外围设备进行通信,如传感器、存储器等,为视频处理提供更多的数据源。 总结来说,hisi16ev200是一款强大的芯片,能够提供强大的视频处理和编码能力,同时支持多种视频接口标准,包括bt1120,为用户提供了更多的接口和数据源选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值