回声消除(AEC)原理、算法及实战——LMS(Least Mean Square)

回声消除是语音通信前端处理中的一种重要技术,产生的原因是:在实时音视频通话中,扬声器播放的声音有再次录进了麦克风去。

在即时通讯应用中,需要进行双方,或是多方的实时语音交流,在要求较高的场合,通常都是采用外置音箱放音,这样必然会产生回音,即一方说话后,通过对方的音箱放音,然后又被对方的Mic采集到回传给自己(如下图所示)。如果不对回音进行处理,将会影响通话质量和用户体验,更严重的还会形成震荡,产生啸叫。

声学回声是指扬声器播出的声音在接受者听到的同时,也通过多种路径被麦克风拾取到。多路径反射的结果产生了不同延时的回声,包括直接回声和间接回声。

直接回声是指由扬声器播出的声音未经任何反射直接进入麦克风。这种回声的延时最短 ,它同远端说话者的语音能量,扬声器与麦克风之间的距离、角度 ,扬声器的播放音量,麦克风的拾取灵敏度等因素直接相关;

间接回声是指由扬声器播出的声音经过不同的路径 (如房屋或房屋内的任何物体 )的一次或多次反射后进入麦克风所产生的回声的集合。房屋内的任何物体的任何变动都会改变回声的通道。因此,这种回声的特点是多路径的、时变的。

  自适应回声消除的基本思想是估计回音路径的特征参数,产生一个模拟的回音路径,得出模拟回音信号,从接收信号中减去该信号,实现回音抵消。其关键就是得到回声路径的冲击响应\hat{h}(n),由于回音路径通常是未知的和时变的,所以一般采用自适应滤波器来模拟回音路径。自适应回音消除的显著特点是实时跟踪,实时性强。

 

 图中y(n)代表来自远端的信号 , r(n)是经过回声通道而产生的回声,x(n)是近端的语音信号。D端是近端麦克风,麦克风采集到的房间叠加的回声和近端说话人的语音。对回声消除器来说,接收到的远端信号作为一个参考信号,回声消除器根据参考信号由自适应滤波器产生回声的估计值\hat{r}(n),将\hat{r}(n)从近端带有回声的语音信号减去,就得到近端传送出去的信号 。在理想且是单讲的情况下,经过回声消除器处理后,残留的回声误差e(n)=r(n)−\hat{r}(n)将为0,从而实现回音消除。若是双讲的情况(近端有人说话,远端也在说话,而且还存在回声的情况下),希望回声误差e(n)对于近端的语音信号。

性能指标:

  • 收敛速度:滤波器的收敛速度越快越好,使正常通话开始后,通话者很快就感觉不到明显的回波存在。
  • 稳态残留回波(稳定性):即当滤波器收敛达到稳态后的回波输出量,实际中总是希望该参数越小越好。
  • 算法复杂度:良好的算法应该在保持收敛速度的同时尽量降低计算复杂度,同时也能减少功耗

ITU-T G.168对各种回音抵消器产品在包括以上两个主要指标在内的各种指标规定了必须达到的标准

AEC技术的基本原理如下图所示:

 

 程序如下:

import numpy as np
import librosa
import soundfile as sf
import pyroomacoustics as pra
# x 参考信号
# d 麦克风信号
# N 滤波器阶数
# mu 迭代步长
def lms(x, d, N = 4, mu = 0.1):
  nIters = min(len(x),len(d)) - N
  u = np.zeros(N)
  w = np.zeros(N)
  e = np.zeros(nIters)
  for n in range(nIters):
    u[1:] = u[:-1]
    u[0] = x[n]
    e_n = d[n] - np.dot(u, w)
    w = w + mu * e_n * u
    e[n] = e_n
  return e

# x 原始参考信号
# v 理想mic信号 
# 生成模拟的mic信号和参考信号
def creat_sim_sound(x,v):
    rt60_tgt = 0.08
    room_dim = [2, 2, 2]

    e_absorption, max_order = pra.inverse_sabine(rt60_tgt, room_dim)
    room = pra.ShoeBox(room_dim, fs=sr, materials=pra.Material(e_absorption), max_order=max_order)
    room.add_source([1.5, 1.5, 1.5])
    room.add_microphone([0.1, 0.5, 0.1])
    room.compute_rir()
    rir = room.rir[0][0]
    rir = rir[np.argmax(rir):]
    # x 经过房间反射得到 y
    y = np.convolve(x,rir)
    scale = np.sqrt(np.mean(x**2)) /  np.sqrt(np.mean(y**2))
    # y 为经过反射后到达麦克风的声音
    y = y*scale

    L = max(len(y),len(v))
    y = np.pad(y,[0,L-len(y)]) # 补零,使其信号长度一致
    v = np.pad(v,[L-len(v),0]) # 补零,使其信号长度一致
    x = np.pad(x,[0,L-len(x)]) # 补零,使其信号长度一致
    d = v + y
    return x,d

if __name__ == "__main__":
    x_org, sr  = librosa.load('female.wav',sr=8000)
    v_org, sr  = librosa.load('male.wav',sr=8000)  # 采样率为8000,不加sr的话默认是22kHz

    x,d = creat_sim_sound(x_org,v_org)

    e =  lms(x, d,N=256,mu=0.1)
    sf.write('x.wav', x, sr, subtype='PCM_16')
    sf.write('d.wav', d, sr, subtype='PCM_16')
    sf.write('lms.wav', e, sr, subtype='PCM_16')

参考资料:

https://www.bilibili.com/video/BV1LP411j7yy/?spm_id_from=333.788&vd_source=77c874a500ef21df351103560dada737

https://www.cnblogs.com/LXP-Never/p/11773190.html 

  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的。 AEC(自适应增益控制)的LMS(最小均方误差)方法是一种常用的自适应滤波器算法,它可以用来估计时变信号的线性模型并对其进行滤波。 下面是使用C语言实现LMS方法的简要步骤: 1. 初始化滤波器系数向量w。 2. 从输入信号中读入一个新的样本x[n]。 3. 使用当前的滤波器系数向量w计算输出信号y[n]。 4. 使用目标信号d[n]和输出信号y[n]计算误差信号e[n]。 5. 使用LMS算法的权重更新公式更新滤波器系数向量w。 6. 重复步骤2-5,直到达到指定的迭代次数或者满足停止条件。 具体的,LMS算法的权重更新公式为: w[n+1] = w[n] + 2 * mu * e[n] * x[n] 其中,mu为步长系数,决定了每次更新时权重的变化幅度。 这是一种基本的LMS算法,其他变种的LMS算法也存在,但它们的基本思想和流程是相似的。 希望这些信息能帮助您。 ### 回答2: 自适应回声消除AEC)是一种常见的数字信号处理技术,用于在语音通信中抑制回声。其中最常用的算法之一是最小均方(LMS算法。下面是使用C语言实现AECLMS方法的一个简单示例: ```c #include <stdio.h> #define N 256 // 输入信号的长度 #define M 128 // FIR滤波器的阶数 #define mu 0.01 // 自适应步长 int main() { float x[N]; // 输入信号 float d[N]; // 所期望的输出信号 float h[M]; // FIR滤波器的系数 float e; // 滤波器输出与期望输出之间的误差 float y; // 滤波器的输出信号 // 初始化输入信号、期望输出信号和滤波器系数 // ... // 执行LMS算法 for (int i = M; i < N; i++) { // 滤波器的输出 y = 0; for (int j = 0; j < M; j++) { y += x[i-j] * h[j]; } // 计算误差 e = d[i] - y; // 更新滤波器系数 for (int j = 0; j < M; j++) { h[j] += mu * e * x[i-j]; } } // 输出滤波器的系数 for (int i = 0; i < M; i++) { printf("h[%d] = %f\n", i, h[i]); } return 0; } ``` 在上面的示例中,我们首先定义了输入信号`x`、期望输出信号`d`和FIR滤波器的系数`h`。然后,通过嵌套的循环实现LMS算法的迭代过程。每次迭代中,我们计算滤波器的输出`y`,并根据期望输出信号和滤波器输出信号之间的误差`e`来更新滤波器系数。 最后,我们输出更新后的滤波器系数`h`。这些系数可以用于实时语音通信中的自适应回声消除。 这只是一个简单的示例,实际的AEC系统可能需要更多的功能和复杂性。如果要实现更高级的AEC算法,请参考相关的文献和资源。 ### 回答3: 自适应增益控制(AEC)是一种常用的语音增强技术,可用于减少语音信号中的回声噪声。使用最小均方(LMS算法可以有效地实现AEC功能。 LMS算法的思想是通过不断更新滤波器的权值,使滤波器的输出信号尽可能地接近期望输出信号。具体步骤如下: 1. 初始化滤波器的权值向量w和延迟线缓冲器x,将它们初始化为0。 2. 从麦克风中获取输入语音信号x和回声输入信号d。 3. 根据当前权值计算滤波器的输出信号y,即y = w * x,其中*表示向量内积操作。 4. 计算当前预测误差e = d - y。 5. 根据LMS算法的公式更新权值:w = w + μ * e * x,其中μ是自适应步长,用于控制权值更新的速度。 6. 将输入信号放入延迟线缓冲器x中,以便下一次迭代。 7. 重复步骤2至6,直到达到预定的迭代次数或预测误差趋近于0。 8. 最后,从滤波器中获取输出信号y,这是经过AEC处理后的语音信号。 通过使用C语言,我们可以实现以上描述的LMS算法,代码示例如下: ```c #include <stdio.h> #define N 1024 // 缓冲器的大小 #define mu 0.01 // 自适应步长 void LMS_AEC(float *x, float *d, float *y, float *w) { float e; float x_buffer[N] = {0}; // 缓冲器 e = *d - (*w * (*x)); // 计算预测误差 for (int i = N - 1; i >= 1; i--) { x_buffer[i] = x_buffer[i - 1]; // 更新缓冲器中的数据 } x_buffer[0] = *x; // 存储最新的输入信号 for (int i = 0; i < N; i++) { *y += (w[i] * x_buffer[i]); // 计算滤波器输出信号 } for (int i = 0; i < N; i++) { w[i] += (mu * e * x_buffer[i]); // 更新权值 } } int main() { float x, d, y = 0; float w[N] = {0}; // 初始化权值 // 获取输入语音信号和回声信号 // ... // 使用LMS_AEC函数进行AEC处理 LMS_AEC(&x, &d, &y, w); // 输出处理后的语音信号 printf("AEC输出信号: %f\n", y); return 0; } ``` 以上就是使用C语言实现AECLMS方法的基本思路和示例代码。根据实际需求,还可以对算法进行优化和改进,例如添加自适应步长控制、加入截断方法等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值