跳转至

SGS AEC 算法使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 09/08/2020
    1.1
  • Modified API
  • 10/15/2020
    1.2
  • Added IaaAec_SetRecursiveRatio function
  • 02/16/2022
    1.21
  • more detail for point number and channel
  • 08/18/2022
    1.22
  • more detail for stereo data arrangement
  • 10/25/2022
    1.23
  • Added IaaAec_ADF_Run and IaaAec_NLP_Run function
  • 03/10/2023
    1.3
  • Added IaaAec_GetAPIVersion and IaaAec_GetConfig function
  • 04/14/2023
    1.31
  • Added input pointer length detail
  • 07/12/2023
    1.4
  • Added IaaAec_SetHandleId function
  • 02/19/2024
    1.5
  • Added IaaAec_GetJsonFileSize, IaaAec_InitReadFromJson,IaaAec_ConfigReadFromJson,IaaAec_OptionReadFromJson function
  • 10/30/2024
    1.51
  • Update description of suppression_mode_freq in AudioAecConfig
  • 03/24/2025
    1.52
  • Update file description and copyright
  • 04/19/2025
    1.53
  • Remove copyright
  • 05/13/2025
    1.54
  • Modify suppression_mode_freq range in AudioAecConfig
  • 07/16/2025
    1.6
  • Added IaaAec_SetADFBlockNum
  • 08/01/2025
    1.7
  • Added IaaAec_SetMode
  • 08/15/2025
    1.71
  • Added IaaAec_SetMode note
  • 09/23/2025
    1.72
  • Fix formatting and textual errors
  • 10/28/2025
    1.73
  • Add and update description of Chapter 1
  • 11/21/2025

    1. 概述


    1.1. 算法说明

    回声消除(Acoustic Echo Cancellation,简称AEC),是一种用于抑制远程回声的功能。

    回声常见于会议系统、楼宇对讲、安防监控等场景,当远程声音从喇叭播放出来后,麦克风在非常小的延时后,重新采集喇叭播放出来的声音并传输回远程,这个延迟的原始信号将导致远程听到回声。

    关键词说明

    • Far-end signal (Sin)

      设备扬声器的信号源,远程传来的信号。

    • Near-end signal (Rin)

      设备麦克风录到的信号,此信号可能包含声学回声(Acoustic echo)和近端语者(Near-end talker)的信号

    • Acoustic echo (AE)

      从设备扬声器播放的声音通过直接或间接路径传回麦克风,产生回声;远程语者在说话后会在延迟某段时间后听到自己的回声,此回声称为声学回声。

    • Single talk

      只有设备端的喇叭播放远程信号(Sin = AE + NS当 NS =0)

    • Double talk

      设备端喇叭播放的同时近端语者也对着麦克风说话(Sin = AE + NS当 NS≠0)

    注意

    为方便调试和确认算法效果,需要使用者应用自行实现替换算法参数和抓取音频数据的逻辑。


    1.2. 基本结构

    当AEC算法配置好内存、完成参数初始化与设定后,AEC需要输入近端讯号Buffer与远程讯号Buffer,并将输入近端讯号Buffer和远程讯号Buffer按设定参数与算法处理后,将处理后数据输出到输入近端讯号Buffer上。


    1.3. 功能介绍

    回声消除 :

    消除近端声音中包含的远程声音,避免产生声学回声。


    1.4. 应用场景

    AEC常用于会议系统、楼宇对讲、安防监控等场景,避免远程系统在讯号发出后延迟某段时间会回录到自己的声学回声。


    1.5. 芯片差异说明

    在不同系列芯片,目前AEC算法效果上没有差异。


    1.6. 实例介绍

    使用AEC API获取AEC算法运行需要的内存大小、初始化AEC算法handle、配置参数至AEC算法handle、运行AEC算法与释放AEC算法资源。

        #include <stdio.h>
        #include <unistd.h>
        #include <fcntl.h>
        #include <string.h>
        #include <time.h>
        #ifndef OS_WINDOWS
        #include <sys/ioctl.h>
        #endif
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <stdlib.h>
        #include <string.h>
        #include <sys/time.h>
    
        #include "AudioAecProcess.h"
    
        #define USE_MALLOC      (1)
        typedef unsigned char   uint8;
        typedef unsigned short  uint16;
        typedef unsigned long   uint32;
    
        float AVERAGE_RUN(int a)
        {
            static unsigned int num = 0;
            static float avg = 0;
    
                if(num == 0)
                    avg = 0;
    
                num++;
                avg = avg + ((float)a - avg) / ((float)num);
    
    
            return avg;
        }
        unsigned int _OsCounterGetMs(void)
        {
            struct  timeval t1;
            gettimeofday(&t1,NULL);
            unsigned int T = ( (1000000 * t1.tv_sec)+ t1.tv_usec ) / 1000;
            return T;
        }
    
        int main(int argc, char *argv[])
        {
            short input[1024];
            short input_aec[1024];
        #if USE_MALLOC
            char *WorkingBuffer2;
        #else
            char WorkingBuffer2 [1024*500];
        #endif
    
            char infileName[512];
            char infileName_aec[512];
            char outfileName[512];
            int counter=0;
            unsigned int T0, T1;
            float avg;
            FILE * fin, * fout, * fin_aec;
            ALGO_AEC_RET ret;
            AudioAecInit aec_init;
            AudioAecConfig aec_config;
            AEC_HANDLE handle;
    
            unsigned int supMode_band[6] = {20,40,60,80,100,120};
            unsigned int supMode[7] = {4,4,4,4,4,4,4};
    
            int PN = 128;
            unsigned int recursive_ratio = 1;
            unsigned int block_num = 8;
            unsigned int mode = 0;
            aec_init.point_number = PN;
            aec_init.nearend_channel = 1;
            aec_init.farend_channel = 1;
            aec_config.delay_sample = 0;
            aec_init.sample_rate = IAA_AEC_SAMPLE_RATE_16000;
            aec_config.comfort_noise_enable = IAA_AEC_FALSE;
            memcpy(&(aec_config.suppression_mode_freq[0]),supMode_band,sizeof(int)*6);
            memcpy(&(aec_config.suppression_mode_intensity[0]),supMode,sizeof(int)*7);
    
        #if USE_MALLOC
            WorkingBuffer2 = (char*)malloc(IaaAec_GetBufferSize());
        #endif
            handle = IaaAec_Init((char*)WorkingBuffer2, &aec_init);
            if (handle==NULL)
            {
                printf("AEC init error\r\n");
                return -1;
            }
            else
            {
                printf("AEC init succeed\r\n");
            }
            sprintf(infileName,"%s",".//..//sample//data//AEC_AFE_16K_mono.wav"); //near
            sprintf(infileName_aec,"%s",".//..//sample//data//I2S_16K_mono.wav"); //far
            sprintf(outfileName,"%s",".//AecOut.wav");
    
            ret = IaaAec_Config(handle ,&(aec_config));
            ret += IaaAec_SetRecursiveRatio(handle, recursive_ratio);
            ret += IaaAec_SetADFBlockNum(handle, block_num);
            ret += IaaAec_SetMode(handle, mode);
            if(ret != ALGO_AEC_RET_SUCCESS)
            {
                printf("Error occured in AEC config function \n");
                return -1;
            }
    
            fin = fopen(infileName, "rb");
            if(!fin)
            {   printf("the input file could not be open\n");
                return -1;
            }
    
            fout = fopen(outfileName, "wb");
            if(!fout)
            {
                printf("the output file could not be open\n");
                return -1;
            }
    
            fread(input, sizeof(char), 44, fin); // read header 44 bytes
            fwrite(input, sizeof(char),44, fout); // write 44 bytes output
    
    
            fin_aec = fopen(infileName_aec, "rb");
            if(!fin_aec)
            {
                printf("the input file could not be open\n");
                return -1;
            }
            fread(input_aec, sizeof(char), 44, fin_aec); // read header 44 bytes
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
            printf("The chip is big-endian!!!\n");
            int k=0;
            short right = 0x0000;
            short left = 0x0000;
        #endif
    
            while(fread(input, sizeof(short), PN*aec_init.nearend_channel, fin))
            {
                fread(input_aec, sizeof(short), PN*aec_init.farend_channel, fin_aec);
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    
    
                for(k=0;k<PN*aec_init.nearend_channel;k++)
                {
                    right = (input[k]>>8)&(0x00ff);
                    left = (input[k]<<8)&(0xff00);
                    input[k] = left|right;
                    right = (input_aec[k]>>8)&(0x00ff);
                    left = (input_aec[k]<<8)&(0xff00);
                    input_aec[k] = left|right;
                }
    
        #endif
                counter++;
    
                T0  = (long)_OsCounterGetMs();
                ret = IaaAec_Run(handle, input , input_aec );
                T1  = (long)_OsCounterGetMs();
                avg = AVERAGE_RUN(T1 - T0);
    
                if(counter%100 == 0)
                {
                    printf("counter = %d\n", counter);
                    printf("current time = %f\n", (float)counter*PN/aec_init.sample_rate);
    
                    printf("process time = %lu(ms)\t",(long)(T1 - T0));
                    printf("AVG is %.2f ms\n",avg);
                }
                if(ret != ALGO_AEC_RET_SUCCESS)
                {
                    printf("Error occured in AEC run function \n");
                    break;
                }
    
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    
    
                for(k=0;k<PN*aec_init.nearend_channel;k++)
                {
                    right = (input[k]>>8)&(0x00ff);
                    left = (input[k]<<8)&(0xff00);
                    input[k] = left|right;
                }
    
        #endif
                fwrite(input, sizeof(short), PN*aec_init.nearend_channel, fout);
    
            }
            ret = IaaAec_Free(handle);
            if(ret != ALGO_AEC_RET_SUCCESS)
            {
                printf("Error occured in AEC free function \n");
                return -1;
            }
            fclose(fin);
            fclose(fin_aec);
            fclose(fout);
    
            printf("Done\n");
        return 0;
        }
    

    使用AEC API读取AEC json档参数、获取AEC算法运行需要的内存大小、初始化AEC算法handle、配置参数至AEC算法handle、运行AEC算法与释放AEC算法资源。

        #include <stdio.h>
        #include <unistd.h>
        #include <fcntl.h>
        #include <string.h>
        #include <time.h>
        #ifndef OS_WINDOWS
        #include <sys/ioctl.h>
        #endif
        #include <sys/types.h>
        #include <sys/stat.h>
        #include <stdlib.h>
        #include <string.h>
        #include <sys/time.h>
    
    
        #include "AudioAecProcess.h"
    
    
        #define PN              (128)
        #define USE_MALLOC      (1)
        typedef unsigned char    uint8;
        typedef unsigned short   uint16;
        typedef unsigned long    uint32;
    
    
        float AVERAGE_RUN(int a)
        {
            static unsigned int num = 0;
            static float avg = 0;
    
                if(num == 0)
                    avg = 0;
    
                num++;
                avg = avg + ((float)a - avg) / ((float)num);
    
    
            return avg;
        }
        unsigned int _OsCounterGetMs(void)
        {
            struct  timeval t1;
            gettimeofday(&t1,NULL);
            unsigned int T = ( (1000000 * t1.tv_sec)+ t1.tv_usec ) / 1000;
            return T;
        }
    
        int main(int argc, char *argv[])
        {
            short input[256];
            short input_aec[256];
        #if USE_MALLOC
            char *WorkingBuffer2;
        #else
            char WorkingBuffer2 [1024*500];
        #endif
    
            char infileName[512];
            char infileName_aec[512];
            char outfileName[512];
            int counter=0;
            unsigned int T0, T1;
            float avg;
            FILE * fin, * fout, * fin_aec;
    
    
            char aec_para_json_file[512];
            sprintf(aec_para_json_file,"%s","./../sample/data/AecParamJson.json");
            unsigned int aec_para_buffersize = IaaAec_GetJsonFileSize(aec_para_json_file);
    
    
        #if USE_MALLOC
            WorkingBuffer2 = (char*)malloc(IaaAec_GetBufferSize());
            char *aec_para_json_buf_ptr = (char*)malloc(aec_para_buffersize);
        #endif
    
            ALGO_AEC_RET ret;
            AudioAecInit aec_init;
            AudioAecConfig aec_config;
            AEC_HANDLE handle;
            AudioAecOption aec_option;
    
            memset(&aec_init,0,sizeof(AudioAecInit));
            memset(&aec_config,0,sizeof(AudioAecConfig));
            memset(&aec_option,0,sizeof(AudioAecOption));
            ret = IaaAec_InitReadFromJson(&aec_init, aec_para_json_buf_ptr, aec_para_json_file, aec_para_buffersize);
            ret += IaaAec_ConfigReadFromJson(&aec_config, aec_para_json_buf_ptr, aec_para_json_file, aec_para_buffersize);
            ret += IaaAec_OptionReadFromJson(&aec_option, aec_para_json_buf_ptr, aec_para_json_file, aec_para_buffersize);
    
    
            handle = IaaAec_Init((char*)WorkingBuffer2, &aec_init);
            if (handle==NULL)
            {
                printf("AEC init error\r\n");
                return -1;
            }
            else
            {
                printf("AEC init succeed\r\n");
            }
            sprintf(infileName,"%s","./../sample/data/AEC_AFE_16K_mono.wav"); //near
            sprintf(infileName_aec,"%s","./../sample/data/I2S_16K_mono.wav"); //far
            sprintf(outfileName,"%s","./../sample/data/AecOut.wav");
    
            ret += IaaAec_Config(handle ,&(aec_config));
            ret += IaaAec_SetRecursiveRatio(handle, aec_option.recursive_ratio);
            ret += IaaAec_SetADFBlockNum(handle, aec_option.block_num);
            ret += IaaAec_SetMode(handle, aec_option.mode);
            if(ret != ALGO_AEC_RET_SUCCESS)
            {
                printf("Error occured in AEC config function \n");
                return -1;
            }
    
            fin = fopen(infileName, "rb");
            if(!fin)
            {   printf("the input file could not be open\n");
                return -1;
            }
    
            fout = fopen(outfileName, "wb");
            if(!fout)
            {
                printf("the output file could not be open\n");
                return -1;
            }
    
            fread(input, sizeof(char), 44, fin); // read header 44 bytes
            fwrite(input, sizeof(char),44, fout); // write 44 bytes output
    
    
            fin_aec = fopen(infileName_aec, "rb");
            if(!fin_aec)
            {
                printf("the input file could not be open\n");
                return -1;
            }
            fread(input_aec, sizeof(char), 44, fin_aec); // read header 44 bytes
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
            printf("The chip is big-endian!!!\n");
            int k=0;
            short right = 0x0000;
            short left = 0x0000;
        #endif
    
            while(fread(input, sizeof(short), PN*aec_init.nearend_channel, fin))
            {
                fread(input_aec, sizeof(short), PN*aec_init.farend_channel, fin_aec);
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    
    
                for(k=0;k<PN*aec_init.nearend_channel;k++)
                {
                    right = (input[k]>>8)&(0x00ff);
                    left = (input[k]<<8)&(0xff00);
                    input[k] = left|right;
                    right = (input_aec[k]>>8)&(0x00ff);
                    left = (input_aec[k]<<8)&(0xff00);
                    input_aec[k] = left|right;
                }
    
        #endif
                counter++;
    
                T0  = (long)_OsCounterGetMs();
                ret = IaaAec_Run(handle, input , input_aec );
                T1  = (long)_OsCounterGetMs();
                avg = AVERAGE_RUN(T1 - T0);
    
                if(counter%100 == 0)
                {
                    printf("counter = %d\n", counter);
                    printf("current time = %f\n", (float)counter*PN/aec_init.sample_rate);
    
                    printf("process time = %lu(ms)\t",(long)(T1 - T0));
                    printf("AVG is %.2f ms\n",avg);
                }
                if(ret != ALGO_AEC_RET_SUCCESS)
                {
                    printf("Error occured in AEC run function \n");
                    break;
                }
    
        #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    
    
                for(k=0;k<PN*aec_init.nearend_channel;k++)
                {
                    right = (input[k]>>8)&(0x00ff);
                    left = (input[k]<<8)&(0xff00);
                    input[k] = left|right;
                }
    
        #endif
                fwrite(input, sizeof(short), PN*aec_init.nearend_channel, fout);
    
            }
            ret = IaaAec_Free(handle);
            if(ret != ALGO_AEC_RET_SUCCESS)
            {
                printf("Error occured in AEC free function \n");
                return -1;
            }
            fclose(fin);
            fclose(fin_aec);
            fclose(fout);
    
            printf("Done\n");
        return 0;
        }
    

    2. API 参考


    2.1. 功能模块API

    API名 功能
    IaaAec_GetBufferSize 获取Aec算法运行需要的内存大小
    IaaAec_Init 初始化Aec算法
    IaaAec_Config 配置Aec算法
    IaaAec_Reset 重新初始化Aec算法
    IaaAec_Free 释放Aec算法资源
    IaaAec_Run Aec算法处理
    IaaAec_GetLibVersion 获取Aec算法的版本信息
    IaaAec_SetRecursiveRatio 配置Aec算法recursive ratio参数
    IaaAec_ADF_Run 线性Aec算法处理
    IaaAec_NLP_Run 非线性Aec算法处理
    IaaAec_GetConfig 获取Aec算法的当前配置参数.
    IaaAec_GetAPIVersion 获取Aec版本
    IaaAec_SetHandleId 配置Aec算法id
    IaaAec_GetJsonFileSize Aec获取解析Json文件内容所需要的内存大小
    IaaAec_InitReadFromJson 配置Json参数到Aec算法的初始化结构体指针
    IaaAec_ConfigReadFromJson 配置Json参数到Aec算法的配置结构体指针
    IaaAec_OptionReadFromJson 配置Json参数到Aec算法的其他选项结构体指针
    IaaAec_SetADFBlockNum 配置Aec算法在不同取样率下adf block number 参数
    IaaAec_SetMode 配置Aec算法模式

    2.2. IaaAec_GetBufferSize

    • 功能

      获取Aec算法运行所需要的内存大小。

    • 语法

      unsigned int IaaAec_GetBufferSize(void);
      
    • 形参

      参数名称 描述 输入/输出
    • 返回值

      返回值为Aec算法运行所需要的内存大小

    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      该接口仅返回需要的内存大小,申请和释放内存的动作需应用来处理。

    • 举例

      无。


    2.3. IaaAec_Init

    • 功能

      初始化Aec算法需要的内存。

    • 语法

      AEC_HANDLE IaaAec_Init(char* working_buffer_address, AudioAecInit * aec_init);
      
    • 形参

      参数名称 描述 输入/输出
      working_buffer_address Aec算法使用的内存地址 输入
      aec_init Aec算法的初始化结构体指针 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • Aec算法仅支援8K/16K采样率。
    • 举例

      无。


    2.4. IaaAec_Config

    • 功能

      配置Aec算法。

    • 语法

      ALGO_AEC_RET IaaAec_Config(AEC_HANDLE handle, AudioAecConfig *aec_config);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
      aec_config Aec算法配置参数的结构体指针 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      无。

    • 举例

      无。


    2.5. IaaAec_Reset

    • 功能

      重新初始化Aec算法的内存。

    • 语法

      AEC_HANDLE IaaAec_Reset(char* working_buffer_address, AudioAecInit * aec_init);
      
    • 形参

      参数名称 描述 输入/输出
      working_buffer_address Aec算法所使用的内存地址 输入
      aec_init Aec算法的初始化结构体指针 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • 针对同一个算法handle(同一内存地址)重新初始化Aec算法(即重新设置采样率和近远程的通道数)

      • 重新初始化Aec算法后,需要重新配置

    • 举例

      无。


    2.6. IaaAec_Free

    • 功能

      释放Aec算法的资源

    • 语法

      ALGO_AEC_RET IaaAec_Free(AEC_HANDLE handle);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • 必须先调用IaaAec_Free,再释放供Aec算法所使用的内存。
    • 举例

      无。


    2.7. IaaAec_Run

    • 功能

      Aec算法处理

    • 语法

      ALGO_AEC_RET IaaAec_Run(AEC_HANDLE handle, short* pss_audio_near_end, short* pss_audio_far_end);
      
    • 形参

      参数名称 描述 输入/输出
      handle 算法handle 输入
      pss_audio_near_end 近端数据指针 输入/输出
      pss_audio_far_end 远程数据指针 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • 近远程的数据量必须和调用IaaAec_Init时设定的point_number(一次IaaAec_Run所需要的采样点数)相对应。

      • AEC后结果由pss_audio_near_end输出。

      • 若输入为双声道,请自行将其依据左右左右排列分割成左声道与右声道两个数组。

    • 举例


    2.8. IaaAec_GetLibVersion

    • 功能

      获取Aec算法的版本信息

    • 语法

      ALGO_AEC_RET IaaAec_GetLibVersion(unsigned short *ver_year, unsigned short *ver_date,  unsigned short *ver_time);
      
    • 形参

      参数名称 描述 输入/输出
      ver_year Aec算法库档编译时的年份 输出
      ver_date Aec算法库档编译时的日期 输出
      ver_time Aec算法库档编译时的时间 输出
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      无。

    • 举例

      无。


    2.9. IaaAec_SetRecursiveRatio

    • 功能

      配置Aec算法recursive ratio参数。

    • 语法

      ALGO_AEC_RET IaaAec_SetRecursiveRatio(AEC_HANDLE handle, unsigned int recursive_ratio);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
      recursive_ratio 递归参数输入。参数设置越大,递归更新讯号速度越快,在Double talk切换到Single talk后,减少回声过度消除近端讯号情形,相对回声消除平顺度降低,背景残留回声不连续性提高。
      取值范围:1 ~ 10
      输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 举例

      无。


    2.10. IaaAec_ADF_Run

    • 功能

      线性Aec算法处理

    • 语法

      ALGO_AEC_RET IaaAec_ADF_Run(AEC_HANDLE handle, short* pss_audio_near_end, short* pss_audio_far_end);
      
    • 形参

      参数名称 描述 输入/输出
      handle 算法handle 输入
      pss_audio_near_end 近端数据指针 输入/输出
      pss_audio_far_end 远程数据指针 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • 近远程的数据量必须和调用IaaAec_Init时设定的point_number(一次IaaAec_ADF_Run所需要的采样点数)相对应。

      • AEC后结果由pss_audio_near_end输出

      • 若输入为双声道,请自行将其依据左右左右排列分割成左声道与右声道两个数组。

    • 举例

      无。


    2.11. IaaAec_NLP_Run

    • 功能

      非线性Aec算法处理

    • 语法

      ALGO_AEC_RET IaaAec_NLP_Run(AEC_HANDLE handle, short* pss_audio_near_end);
      
    • 形参

      参数名称 描述 输入/输出
      handle 算法handle 输入
      pss_audio_near_end 近端数据指针 输入/输出
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      • 近远程的数据量必须和调用IaaAec_Init时设定的point_number(一次IaaAec_NLP_Run所需要的采样点数)相对应。

      • AEC后结果由pss_audio_near_end输出

      • 若输入为双声道,请自行将其依据左右左右排列分割成左声道与右声道两个数组。

    • 举例

      无。


    2.12. IaaAec_GetConfig

    • 功能

      获取Aec算法的当前配置参数

    • 语法

      ALGO_AEC_RET IaaAec_GetConfig(AEC_HANDLE handle, AudioAecInit * aec_init, AudioAecConfig *aec_config);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec 算法handle 输入
      aec_init Aec算法的初始化结构体指针 输出
      aec_config Aec算法配置参数的结构体指针 输出
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 举例

      无。


    2.13. IaaAec_GetAPIVersion

    • 功能

      获取AEC版本

    • 语法

      ALGO_AEC_RET IaaAec_GetAPIVersion(unsigned short* major, unsigned short* minor);
      
    • 形参

      参数名称 描述 输入/输出
      major 算法版本 输出
      minor 算法版本 输出
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 举例

      无。


    2.14. IaaAec_SetHandleId

    • 功能

      配置Aec算法id

    • 语法

      ALGO_AEC_RET IaaAec_SetHandleId(AEC_HANDLE handle, int id);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
      id Aec算法handle id
      数值范围:[0,100]
      输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参考错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 举例

      无。


    2.15. IaaAec_GetJsonFileSize

    • 功能

      Aec获取解析Json文件内容所需要的内存大小

    • 语法

      unsigned int IaaAec_GetJsonFileSize(char* jsonfile);
      
    • 形参

      参数名称 描述 输入/输出
      jsonfile Json檔名 输入
    • 返回值

      返回值为解析Json文件内容所需要的内存大小

    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a


    2.16. IaaAec_InitReadFromJson

    • 功能

      配置Json参数到Aec算法的初始化结构体指针

    • 语法

      ALGO_AEC_RET IaaAec_InitReadFromJson(AudioAecInit *aec_init, char* jsonBuffer, char* jsonfile, unsigned int buffSize);
      
    • 形参

      参数名称 描述 输入/输出
      aec_init Aec算法的初始化结构体指针 输入/输出
      jsonBuffer 解析Json文件内容所使用的内存地址 输入
      jsonfile Json檔名 输入
      buffSize 解析Json文件内容所需要的内存大小 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参考错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a


    2.17. IaaAec_ConfigReadFromJson

    • 功能

      配置Json参数到Aec算法的配置结构体指针

    • 语法

      ALGO_AEC_RET IaaAec_ConfigReadFromJson(AudioAecConfig *aec_config, char* jsonBuffer, char* jsonfile, unsigned int buffSize);
      
    • 形参

      参数名称 描述 输入/输出
      aec_config Aec算法的配置结构体指针 输入/输出
      jsonBuffer 解析Json文件内容所使用的内存地址 输入
      jsonfile Json檔名 输入
      buffSize 解析Json文件内容所需要的内存大小 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参考错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a


    2.18. IaaAec_OptionReadFromJson

    • 功能

      配置Json参数到Aec算法的其他选项结构体指针

    • 语法

      ALGO_AEC_RET IaaAec_OptionReadFromJson(AudioAecOption* aec_option, char* jsonBuffer, char* jsonfile, unsigned int buffSize);
      
    • 形参

      参数名称 描述 输入/输出
      aec_option Aec算法的其他选项结构体指针 输入/输出
      jsonBuffer 解析Json文件内容所使用的内存地址 输入
      jsonfile Json檔名 输入
      buffSize 解析Json文件内容所需要的内存大小 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参考错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      此算法读取jsonfile内其他选项设定参数至AudioAecOption结构体,提供给 IaaAec_SetRecursiveRatioAPI函式使用


    2.19. IaaAec_SetADFBlockNum

    • 功能

      配置Aec算法在不同取样率下adf block number 参数。

    • 语法

      ALGO_AEC_RET IaaAec_SetADFBlockNum(AEC_HANDLE handle, unsigned int block_num);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
      block_num 线性Aec滤波器数量。线性声学回声消除(AEC)滤波器。其在不同采样率下有着特定的 block_num 设定上限:8kHz/16kHz 时最大为 8,32kHz 时为 16,48kHz 时则为 24。这些限制取决于算法库是否支持扩增线性 AEC 滤波器的数量。 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 举例

      无。


    2.20. IaaAec_SetMode

    • 功能

      配置Aec算法模式。

    • 语法

      ALGO_AEC_RET IaaAec_SetMode(AEC_HANDLE handle, unsigned int mode);
      
    • 形参

      参数名称 描述 输入/输出
      handle Aec算法handle 输入
      mode 不同 AEC 模式。 模式 0 为默认 AEC 传统算法。模式 1 为结合深度学习非线性处理。 输入
    • 返回值

      返回值 结果
      0 成功
      非0 失败,参照错误码
    • 依赖

      • 头文件: AudioAecProcess.h

      • 库文件: libAEC_LINUX.so/ libAEC_LINUX.a

    • 注意

      模式 1 仅支持 16K 取样率。

    • 举例

      无。


    3. AEC 数据类型


    3.1. AEC模块相关数据类型定义

    数据类型 定义
    AudioAecInit Aec算法初始化参数数据结构体类型
    AudioAecConfig Aec算法配置参数数据结构体类型
    IAA_AEC_SAMPLE_RATE Aec算法支持的采样率类型
    IAA_AEC_BOOL Aec算法的布尔类型
    AEC_HANDLE Aec算法句柄类型
    AudioAecOption Aec算法其他选项参数结构体类型

    3.2. AudioAecInit

    • 说明

      定义Aec算法的初始化参数结构体。

    • 定义

      typedef struct
      
      {
      
          unsigned int point_number;
      
          unsigned int nearend_channel;
      
          unsigned int farend_channel;
      
          IAA_AEC_SAMPLE_RATE sample_rate;
      
      }AudioAecInit;
      
    • 成员

      成员名称 描述
      point_number Aec算法处理一次的采样点数,预设可支持为128亦可透过下面指令确认可支持的处理点数
       strings libAEC_LINUX.a | grep ALGO 
      nearend_channel 近端的信道数(即麦克风的信道数),可设定单声道或双声道
      范围:[1, 2]
      farend_channel 远程的信道数(即喇叭的通道数),可设定单声道或双声道
      范围:[1, 2]
      sample_rate Aec算法处理的采样率
    • 注意事项

      • 若使用的输入为双声道,请依照左右声道交错排列的方式给讯号,例如:左/右/左/右...

      • IaaAec_Run读取近端数据指针的长度为 $point_number \times nearend_channel \times 2 $ bytes

      • IaaAec_Run 读取远程数据指针的长度为 $point_number \times farend_channel \times 2 $ bytes

      • 若设定为双声道,AEC会把两个声道平均为一个声道处理,并将处理后结果复制到两个声道,如需两声道分开,请初始化两个handle,分开执行IaaAec_Run

    • 相关数据类型及接口

      IaaAec_Init

      IaaAec_Reset

      IaaAec_InitReadFromJson


    3.3. AudioAecConfig

    • 说明

      定义Aec算法的配置参数结构体。

    • 定义

      typedef struct
      
      {
      
          IAA_AEC_BOOL comfort_noise_enable;
      
          short delay_sample;
      
          unsigned int suppression_mode_freq[6];
      
          unsigned int suppression_mode_intensity[7];
      
      }AudioAecConfig;
      
    • 成员

      成员名称 描述
      comfort_noise_enable 在AEC后加入舒适噪声,避免回声消除后部分段落静音,让用户有断线的感觉。 若AEC后有开启Noise reduction,建议开启comfort noise,帮助NR收敛噪声。
      delay_sample 左右声道间的回声延迟样本 当Stereo cost down 开启时,可以根据麦克风摆放位置先行设定样本延迟数,减少双声道所需运算量。 默认为0,单位是sample数 取值范围:-9-9
      suppression_mode_freq AEC处理的频段划分,将不同取样率所能解析的最高频率等分成128等分,设定六个值可切出七个段落设定不同AEC强度。 取值范围:0-128
      suppression_mode_intensity 配合suppression_mode_freq所切割出来的七个段落分别设定七种强度。 取值范围:0-25
    • 注意事项

      • comfort_noise_enable

        使能该参数后,AEC算法会在没有声音时添加一些舒适噪声。当客户对稳定的底噪有要求或AEC消得太干净导致NR收敛时间太长时,可使能该功能。

      • delay_sample

        由于麦克风和喇叭的放置位置、麦克风间的距离等会造成左右声道接收到回声的时间点不一致,两个声道之间回声延迟有差异。此值表示左声道比右声道提早多少个采样点收到回声。可以调整此值来对齐左右声道的资料,设置时,请以左声道作为参考。例如左声道的回声比右声道的回声快4个样本,则s16DelaySample设置为4,反之设置为-4。

      • suppression_mode_freq

        该数组将当前采样率的最高频率分成7个频段来处理。以下数组元素和频率范围的转换公式:

        residual\ Echo\ Frequency\ Range/(sampleRate/2) \times pointNumber(128)

        数组要求每一个元素都必须比前一个元素大。

      • suppression_mode_intensity

        该数组代表各个频段的回声消除强度,各个元素与u32AecSupfreq划分出来的7个频段一一对应。强度越大,消除的细节越多,声音越不自然。

    • 相关数据类型及接口

      IaaAec_Config

      IaaAec_GetConfig

      IaaAec_ConfigReadFromJson


    3.4. IAA_AEC_SAMPLE_RATE

    • 说明

      AEC算法支持的采样率类型。

    • 定义

      typedef enum
      
      {
      
          IAA_AEC_SAMPLE_RATE_8000 = 8000 ,
      
          IAA_AEC_SAMPLE_RATE_16000 = 16000 ,
      
          IAA_AEC_SAMPLE_RATE_32000 = 32000 ,
      
          IAA_AEC_SAMPLE_RATE_48000 = 48000 ,
      
      }IAA_AEC_SAMPLE_RATE;
      
    • 成员

      成员名称 描述
      IAA_AEC_SAMPLE_RATE_8000 8K采样率
      IAA_AEC_SAMPLE_RATE_16000 16K采样率
      IAA_AEC_SAMPLE_RATE_32000 32K采样率
      IAA_AEC_SAMPLE_RATE_48000 48K采样率
    • 注意事项

      模式 1 仅支持 16K 取样率

    • 相关数据类型及接口

      AudioAecInit


    3.5. IAA_AEC_BOOL

    • 说明

      定义Aec算法内部使用的布尔类型。

    • 定义

      typedef enum
      
      {
      
          IAA_AEC_TRUE = 1,
      
          IAA_AEC_FALSE = 0,
      
      }IAA_AEC_BOOL;
      
    • 成员

      成员名称 描述
      IAA_AEC_TRUE True
      IAA_AEC_FALSE False
    • 注意事项

    • 相关数据类型及接口

      AudioAecConfig


    3.6. AEC_HANDLE


    3.7. AudioAecOption


    4. Error code

    AEC API 错误码如表下所示:

    错误码 宏定义 描述
    0x00000000 ALGO_AEC_RET_SUCCESS AEC运行成功
    0x10000401 ALGO_AEC_RET_INIT_ERROR AEC尚未初始化
    0x10000402 ALGO_AEC_RET_INVALID_HANDLE HANDLE无效
    0x10000403 ALGO_AEC_RET_INVALID_SAMPLE_RATE 取样频率不支持
    0x10000404 ALGO_AEC_RET_INVALID_POINT_NUMBER 每帧点数不支持
    0x10000405 ALGO_AEC_RET_INVALID_CHANNEL 通道数不支持
    0x10000406 ALGO_AEC_RET_INVALID_ENABLE 呼叫不支持
    0x10000407 ALGO_AEC_RET_INVALID_SUP_BAND AEC抑制频带参数设置无效
    0x10000408 ALGO_AEC_RET_INVALID_SUP_MODE AEC抑制强度参数设置无效
    0x10000409 ALGO_AEC_RET_INVALID_COMFORT_NOISE AEC舒适噪声参数设置无效
    0x10000410 ALGO_AEC_RET_INVALID_DELAY_SAMPLE AEC延迟样本数设置无效
    0x10000411 ALGO_AEC_RET_INVALID_RECURSIVE_RATIO AEC递归参数设置无效
    0x10000412 ALGO_AEC_RET_API_CONFLICT 其他API正在运行
    0x10000413 ALGO_AEC_RET_INVALID_CALLING 呼叫API顺序错误
    0x10000414 ALGO_AEC_RET_INVALID_JSONFILE AEC 读取Json档失败