SGS AEC 算法使用参考¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 09/08/2020 | |
| 1.1 | 10/15/2020 | |
| 1.2 | 02/16/2022 | |
| 1.21 | 08/18/2022 | |
| 1.22 | 10/25/2022 | |
| 1.23 | 03/10/2023 | |
| 1.3 | 04/14/2023 | |
| 1.31 | 07/12/2023 | |
| 1.4 | 02/19/2024 | |
| 1.5 | 10/30/2024 | |
| 1.51 | 03/24/2025 | |
| 1.52 | 04/19/2025 | |
| 1.53 | 05/13/2025 | |
| 1.54 | 07/16/2025 | |
| 1.6 | 08/01/2025 | |
| 1.7 | 08/15/2025 | |
| 1.71 | 09/23/2025 | |
| 1.72 | 10/28/2025 | |
| 1.73 | 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 ALGOnearend_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
-
-
相关数据类型及接口
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个频段一一对应。强度越大,消除的细节越多,声音越不自然。
-
-
相关数据类型及接口
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 取样率
-
相关数据类型及接口
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 -
注意事项
无
-
相关数据类型及接口
3.6. AEC_HANDLE¶
-
说明
定义Aec算法的句柄类型。
-
定义
typedef void* AEC_HANDLE; -
成员
成员名称 描述 -
注意事项
无
-
相关数据类型及接口
3.7. AudioAecOption¶
-
说明
定义Aec法其他选项参数结构体类型
-
定义
typedef struct { unsigned int recursive_ratio; unsigned int block_num; unsigned int mode; }AudioAecOption; -
成员
成员名称 描述 recursive_ratio 请参考IaaAec_SetRecursiveRatio block_num 请参考IaaAec_SetADFBlockNum mode 请参考IaaAec_SetMode -
注意事项
无
-
相关数据类型及接口
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档失败 |