首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌入式软件中的声学回波消除(AEC)

嵌入式软件中的声学回波消除(AEC)
EN

Stack Overflow用户
提问于 2012-07-05 10:59:34
回答 2查看 6.1K关注 0票数 2

我正在做一个关于嵌入式设备的VoIP项目。我已经建立了一个使用32位MCU与低级音频编解码器的样本。现在我发现我的设备有回声问题,也就是我能从扬声器听到我说的话。我做了一些研究,发现大多数应用程序都使用具有回声消除功能DSP编解码器。但是,是否可以使用我的32位MCU在软件中进行回声消除?

你能提供算法,甚至源代码:p,来做回声消除吗?我知道复杂的方法在MCU上是不可能的,而简单的算法也是受欢迎的。

谢谢

跟踪:我已经尝试了一些AEC代码,但他们不能很好地工作在我的MCU中,可能是MCU能力的限制。我发现在实现这些代码时,我的设备变得非实时(但VoIP需要实时响应)。最后,我通过添加AEC芯片实现了一个模拟硬件解决方案,因为我不想在另一个DSP芯片上重复编写代码。

EN

回答 2

Stack Overflow用户

发布于 2013-09-05 14:03:15

回声消除让我度过了一段艰难的时光。我写了一个软电话,用户可以根据自己的喜好切换音频输入和输出设备。我尝试了Speex回声消除库,以及我在网上找到的其他几个开源库。没有一个对我来说效果很好。我尝试了不同的扬声器/麦克风配置,回声总是以某种形式或方式出现在那里。

我相信要创建适用于所有可能的扬声器配置/房间大小/背景noises..etc的AEC代码将是非常困难的。最后,我坐下来,用这个算法为我的软电话写了自己的回声消除模块。

它有点粗糙,但它工作得很好,而且是可靠的。

variable1:记录与你谈话的人说话时的平均振幅。(不考虑静默时间)

variable2:记录输入(麦克风)的平均振幅,但仅当有声音时才记录,不要考虑静音时间。

一旦有音频可以播放-就把麦克风关掉。并假设收听的人没有说话,在最后一个可听音频帧进入播放后150-300毫秒打开麦克风。

如果来自麦克风的音频(您在播放过程中丢弃的)大于(variable2 * 1.5),则开始在指定的持续时间内发送音频输入帧,并在每次输入振幅达到(variable2 * 1.5)时重新设置该持续时间。

这样说话的人就会知道他们被打断了,然后停下来看看他在说什么。如果说话的人没有太多嘈杂的背景,他们可能会听到大部分的打断。

就像我说的,它不是最优雅的,但它不使用大量的资源(CPU,内存),而且它实际上工作得很好。我对我的声音非常满意。

为了实现它,我只做了几个函数。

在接收到的音频帧上,我调用了我调用的函数:

代码语言:javascript
复制
void audioin( AEC *ec, short *frame ) {
    unsigned int tas=0; /* Total sum of all audio in frame (absolute value) */
    int i=0;
    for (;i<160;i++)
        tas+=ABS(frame[i]);
    tas/=160; /* 320 byte frames muLaw */
    if (tas>300) { /* I assume this is audiable */
        lockecho(ec);
        ec->lastaudibleframe=GetTickCount64();
        unlockecho(ec);
    }
    return;
}

在发送帧之前,我会这样做:

代码语言:javascript
复制
#define ECHO_THRESHOLD 300 /* Time to keep suppression alive after last audible frame */
#define ONE_MINUTE 3000 /* 3000 20ms samples */
#define AVG_PERIOD 250 /* 250 20ms samples */
#define ABS(x) (x>0?x:-x)


char removeecho( AEC *ec, short *aecinput ) {
    int tas=0; /* Average absolute amplitude in this signal */
    int i=0;
    unsigned long long *tot=0;
    unsigned int *ctr=0;
    unsigned short *avg=0;
    char suppressframe=0;
    lockecho(ec);
    if (ec->lastaudibleframe+ECHO_THRESHOLD > GetTickCount64() ) {
        /* If we're still within the threshold for echo (speaker state is ON) */
        tot=&ec->t_aiws;
        ctr=&ec->c_aiws;
        avg=&ec->aiws;
    } else {
        /* If we're outside the threshold for echo (speaker state is OFF) */
        tot=&ec->t_aiwos;
        ctr=&ec->c_aiwos;
        avg=&ec->aiwos;
    }
    for (;i<160;i++) {
        tas+=ABS(aecinput[i]);
    }
    tas/=160;
    if (tas>200) {
        (*tot)+=tas;
        (*avg)=(unsigned short)((*tot)/( (*ctr)?(*ctr):1));
        (*ctr)++;
        if ((*ctr)>AVG_PERIOD) {
            (*tot)=(*avg);
            (*ctr)=0;
        }
    }
    if ( (avg==&ec->aiws) ) {
        tas-=ec->aiwos;
        if (tas<0) {
            tas=0;
        }
        if ( ((unsigned short) tas > (ec->aiws*1.5)) && ((unsigned short)tas>=ec->aiwos) && (ec->aiwos!=0) ) {
            suppressframe=0;
        } else {
            suppressframe=1;
        }
    }
    if (suppressframe) { /* Silence frame */
        memset(aecinput, 0, 320);
    }
    unlockecho(ec);
    return suppressframe;
}

如果需要,它将使帧静音。我将所有变量都保存在AEC结构中,比如计时器和振幅平均值

代码语言:javascript
复制
AEC *initecho( void ) {
    AEC *ec=0;
    ec=(AEC *)malloc(sizeof(AEC));
    memset(ec, 0, sizeof(AEC));
    ec->aiws=200; /* Just a default guess as to what the average amplitude would be */
    return ec;
}





typedef struct aec {
    unsigned long long lastaudibleframe; /* time stamp of last audible frame */
    unsigned short aiws; /* Average mike input when speaker is playing */
    unsigned short aiwos; /*Average mike input when speaker ISNT playing */
    unsigned long long t_aiws, t_aiwos; /* Internal running total (sum of PCM) */
    unsigned int c_aiws, c_aiwos; /* Internal counters for number of frames for     averaging */
    unsigned long lockthreadid; /* Thread ID with lock */
    int stlc; /* Same thread lock-count */
} AEC;

你可以根据你的需要去适应和尝试这个想法,但就像我说的那样。这听起来真的很棒。我唯一的问题是如果他们有很多的背景噪音。但对我来说,如果他们拿起他们的USB手持设备或使用耳机,他们可以关闭回声消除,而不是担心it...but通过PC扬声器与麦克风…我很高兴。

我希望它能帮助你,或者给你一些东西来构建……

票数 3
EN

Stack Overflow用户

发布于 2012-07-14 15:20:32

如果你正在做一个商业项目,这应该是很容易的。您可以在VoIP应用程序中集成商业音频取消软件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11337368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档