背景

我正在设计一个系统,该系统将具有一个用于电话类型设置的单个小型麦克风和扬声器。我可以举的最简单的例子是在Skype对话中,您正在使用计算机扬声器和台式麦克风。

我担心扬声器中的音频会被麦克风拾取并发送回原始音频人。我曾经在VoIP对话的初期就一直听到这种情况,但是几乎听不到了。

我的假设是,小组已经想出了消除回声的方法,但是如何他们做到了吗?

方法

我的第一个想法是只从麦克风信号中减去发送到扬声器的信号,除非使用这种方法关注延迟。我不确定如何在没有某种预校准的情况下确定延迟是什么,我想避免这种情况。还有一个问题是在减去信号之前要先缩放多少信号。

我接下来考虑在扬声器信号和麦克风信号之间进行某种相关以确定信号的可能性。麦克风信号既可以作为回波,又可以确定实际延迟。当我在播放一些记录的信号时,该方法可以正常工作,但是在计算相关性以在实时系统中有用时,似乎存在很大的延迟。另外,扬声器的音量可调使得很难确定某些东西是否真正相关。

我的下一个想法是,互联网上一定有人成功地做到了这一点,但是没有做到。找不到任何很好的例子。所以我来这里看看可以使用什么方法来解决这类问题。

评论

回声消除是一个很大的主题领域,涉及该主题的书籍和研究论文已有数十年之久。这是关于此主题的一个SO问答:stackoverflow.com/questions/3403152/acoustic-echo-cancellation-in-java

@ hotpaw2不确定为什么无法单击Java链接中的回声消除功能。

请建议我,我正在尝试消除语音中存在的回声,即输入到礼堂中单个麦克风的声音。我正在尝试,就像您提到的自适应滤波器一样,因为您正在提供参考信号作为远端通话。但我这里没有参考信号。我的信号是原始信号的回声,接收到的声音可以说是500毫秒,扬声器信号到麦克风。

#1 楼

你是对的。存在许多回声消除方法,但没有一个是简单的。最通用和流行的方法是通过自适应滤波器进行回声消除。一句话,自适应滤波器的作用是通过最小化来自输入的信息量来更改其正在播放的信号。

自适应滤波器

自适应(数字)滤波器是一种会更改其系数并最终收敛到某个最佳配置的滤波器。通过将滤波器的输出与某个所需的输出进行比较,可以进行这种调整。下面是一个通用自适应滤波器的示意图:从图中可以看出,信号$ x [n] $被(卷积)滤波了。 $ \ vec {w} _n $产生输出信号$ \ hat {d} [n] $。然后,我们从所需信号$ d [n] $中减去$ \ hat {d} [n] $,以产生误差信号$ e [n] $。请注意,$ \ vec {w} _n $是系数的向量,而不是数字(因此,我们不写$ w [n] $)。因为它每次迭代都会改变(每个样本),所以我们用$ n $下标这些系数的当前集合。一旦获得了$ e [n] $,我们就可以使用它通过选择的更新算法来更新$ \ vec {w} _n $(稍后会详细介绍)。如果输入和输出满足不随时间变化的线性关系,并给出了设计良好的更新算法,则$ \ vec {w} _n $最终将收敛到最优滤波器,而$ \ hat {d} [n] $将收敛紧跟在$ d [n] $之后。

回声消除

回波消除的问题可以用自适应滤波器问题来表示,在该问题中,我们试图通过找到满足输入输出关系的最佳滤波器来产生给定输入的一些已知理想输出。特别是,当您拿起耳机并说“你好”时,它会在网络的另一端被接收,会被房间的声音响应(如果正在大声播放)改变,然后反馈到网络中以返回对你的回应。但是,由于系统知道初始的“ hello”听起来像什么,现在又知道混响和延迟的“ hello”听起来像什么,因此我们可以尝试猜测使用自适应滤波器的房间响应。然后,我们可以使用该估计值,将所有传入信号与该脉冲响应进行卷积(这将为我们提供回声信号的估计值),然后从进入您呼叫者的麦克风的信号中减去它。下图显示了自适应回声消除器。



在此图中,您的“ hello”信号为$ x [n] $。从扬声器中弹出后,从墙壁上弹起并被设备的麦克风拾起,成为回声信号$ d [n] $。自适应滤波器$ \ vec {w} _n $接受$ x [n] $并产生输出$ y [n] $,收敛后,该输出应理想地跟踪回波信号$ d [n] $。因此$ e [n] = d [n] -y [n] $最终应该归零,因为没有人在通话的另一端通话,通常是在拿起耳机后才出现这种情况说“你好”。这并不总是正确的,稍后将讨论一些不理想的情况。

数学上,NLMS(归一化最小均方)自适应滤波器的实现如下。我们使用上一步的错误信号来更新$ \ vec {w} _n $的每一步。即,让

$$ \ vec {x} _n = \ left(x [n],x [n-1],\ ldots,x [n-N + 1] \ right)^ T $$

其中$ N $是$ \ vec {w} _n $中的抽头(样本)数。注意$ x $的哪些样本是相反的顺序。并让

$$ \ vec {w} _n = \ left(w [0],w [1],\ ldots,x [N-1] \ right)^ T $$

然后我们通过(通过卷积)计算$ y [n] $来找到$ = \ vec {x} _n $和$ = \ vec {w的内积(如果两个信号都是真实的,则为点积) } _n $:

$$ y [n] = \ vec {x} _n ^ T \ vec {w} _n = \ vec {x} _n \ cdot \ vec {w} _n $$

现在我们可以计算误差了,我们正在使用归一化梯度下降方法将其最小化。我们得到$ \ vec {w} $的以下更新规则:

$$ \ vec {w} _ {n + 1} = \ vec {w} _n + \ mu \ vec {x } _n \ frac {e [n]} {\ vec {x} _n ^ T \ vec {x} _n} = \ vec {w} _n + \ mu \ vec {x} _n \ frac {\ vec {x} _n ^ T \ vec {w} _n-d [n]} {\ vec {x} _n ^ T \ vec {x} _n} $$

其中$ \ mu $是自适应步骤大小,使$ 0 \ leq \ mu \ leq 2 $。

现实生活中的应用和挑战

使用回声消除方法,很多事情都会带来困难。首先,如前所述,在接收到您的“ hello”信号时,对方并不总是保持沉默。可以表明(但不在本答复的范围之内),在某些情况下,当线路的另一端存在大量输入时,估计冲激响应仍然有用,因为输入信号和回波是假设在统计上是独立的;因此,最小化错误仍然是有效的过程。通常,需要一种更复杂的系统来检测良好的时间间隔以进行回波估计。

另一方面,请考虑一下,当您试图估计回波时,如果接收到的信号接近静音(实际上是噪声),会发生什么情况。在没有有意义的输入信号的情况下,自适应算法将发散并迅速开始产生无意义的结果,最终达到随机回波模式。这意味着我们还需要考虑语音检测。现代的回声消除器看起来更像下图,但是上面的描述是它的精髓。



那里有很多关于自适应滤波器和回声消除的文献,还有一些可以使用的开源库。

评论


$ \ begingroup $
“自适应滤波器的工作是对信号的”?你不小心说了一个字。
$ \ endgroup $
– Endolith
2014年6月6日15:50

$ \ begingroup $
@endolith谢谢。我想不出一种解决它的好方法,所以我使用了alter。欢迎您使用更有趣的内容对其进行编辑。 =)
$ \ endgroup $
– Phonon
2014年6月6日20:12

#2 楼


我不确定在没有某种预校准的情况下如何确定延迟是什么。


我将从修改声学指纹识别算法开始,例如Shazam。

您的要求在许多方面与Shazam相似(功能必须在为电话设计的压缩算法中有效,并且还必须通过低质量的麦克风),因此您可能会使用相同的功能(本地时间/频率空间中的最大功率),尽管您可能想以频率分辨率为代价来提高时间分辨率。


还有一个问题,就是之前需要缩放信号多少减去它。


均匀缩放几乎肯定不够准确。您需要做一些事情,例如用FIR滤波器近似频率响应,然后将(延迟的)麦克风信号通过反相滤波器,然后再从接收信号中减去它。

评论


$ \ begingroup $
Shazam指纹无法产生准确的延迟近似值。它使用许多复杂的特征提取过程来比较音频样本,但并非全部都是基于时间的。
$ \ endgroup $
– Phonon
2011年10月3日在15:17

$ \ begingroup $
@ Phonon,Shazam现在可能正在使用其他算法,但是链接论文中的算法是基于时间的,可以很好地估计延迟。
$ \ endgroup $
– Finnw
2011年10月3日15:26

$ \ begingroup $
也许诸如发送和接收频谱图的互相关之类的东西会告诉您延迟。应耐过滤和增加噪音
$ \ endgroup $
– Endolith
2014年6月6日20:16