想像一下,你正在机场候机,突然来了一通重要的商务电话,而你身处的背景有嘈杂的交谈声、飞机起飞的噪音、甚至还有机场广播。这个时候打电话就很尴尬,生怕对方听不清自己的声音。
现在,英伟达推出了一款名为2Hz的产品,让你接起电话并开始讲话时,噪声突然消失,电话那头的人听不到任何干扰声音。接下来论智将对这一技术详细介绍,首先通过下面的视频了解下这款产品的效果吧:
两年前,我们决定创建一种技术,当人与人沟通交流时,能完全屏蔽背景噪声,让沟通的过程更愉悦、智能。从那时开始,这个问题就一直成为我们关注的重点。
在这篇文章中,我们会了解,为什么噪声抑制这么难、想创建实时的低延迟噪声抑制系统都需要些什么、以及深度学习是如何帮助我们提高噪声消除的质量的。
目前的噪声抑制技术
首先,我们要知道什么是噪声抑制。在这篇文章中,噪声抑制表示,当你与他人通话时,消除来自你所处背景中的噪声,同时也会消除对方背景中的噪声,如下图所示:
噪声抑制是双向的
传统的噪声抑制方法
传统的噪声抑制技术通常用于一些设备的边缘,例如手机、笔记本电脑、会议系统等等。这种方法看起来很直接,因为设备的边缘是最先捕捉到用户声音的位置。一旦捕捉到声音,设备会将杂音过滤掉,传递到对话的另一端。
十年前,手机通话的体验还非常差。但现在,越来越多的手机会配有多个麦克风,可以帮助抑制环境噪声。
如下图所示,现在的手机通常有两个甚至多个麦克风,最新一代的iPhone有4个。第一个麦克风在手机前面下部,最靠近用户的嘴巴,可以直接捕捉用户声音。手机设计师将第二个麦克风设计得尽量远离第一个麦克风,通常在手机背部的下方。
pixel 2016,黄色区域是麦克风的位置
这两个麦克风都能捕捉到背景声音,不过第一个能捕捉到更多人类声音,第二个收到的人类声音更少。之后通过软件处理,生成一种接近清晰的人声。
这种方法听起来很简单,但事实上失败的次数也很多。例如,当通话者没有说话时,麦克风接收到的全是噪音。或者说话者在打电话过程中会不断晃动手机等等,这种情况就难以处理了。
此外,两个或两个以上的麦克风设计会给生产厂商增加难度,音频/硬件/软件工程师们必须在工业设计和语音质量上做取舍。
目前,手机已经能在嘈杂的环境中表现得不错了,虽然现在的噪声抑制技术还不够完美,但是的确在用户体验上有了极大提升。
当使用分离的麦克风时,尺寸因素又成为了一大问题,如图所示,第一个和第二个麦克风之间的距离必须符合最小距离要求,只有这样才能既让用户听得清,也能让手机捕捉到清晰的人声。
但是,直板似的手机不是唯一的通讯设备。可穿戴设备(智能手表、附着在胸部的麦克风等)、笔记本电脑、平板电脑和智能语音助手等都和手机的设计有所不同。用户会从设备的任意角度、距离进行通话。在大多数情况下,很难有通用的噪声抑制技术。
从多麦克风设计转移到单一麦克风设计
多麦克风的设计有几点重要的缺点:
它对尺寸有一定要求,只能用于手机或头戴设备上;
多麦克风的设计会导致音频路径非常复杂,需要更多硬件和代码的支持。除此之外,第二个麦克风打孔的位置也对工业生成有较高要求;
音频只能在设备边缘处理,所以算法可能无法支持过于复杂的计算。
那么是否有一种方法,可以将多个麦克风合成一个,将所有的后期处理都交给软件?从而硬件设计更简单,也更高效。
传统的数字信号处理(DSP)算法尝试持续寻找噪声模式,逐帧处理音频。这些算法在特定案例中表现得很好,但是无法扩展到日常场景中。
基础噪声的类型有两类:静止和非静止的,如下图所示:
白噪声(静止)和Chirp噪声(非静止)的声谱图
我们可以将静止的噪声想象成一直重复、但和人类语音不同的声音。传统的DSP算法(自适应过滤)在消除这类噪声时很有效。
而非静止噪声的模式非常复杂,和人类声音的模型很相似,难以区分。它们的信号很短,并且出现的速度很快(类似在键盘上打字)。
如果想同时解决以上两种噪声,可能就要突破传统数字信号处理技术了。我们认为,深度学习是解决这一问题的重要方式,所以提出了2Hz。
用深度学习分离背景中的噪声
2015年,Yong Xu等人曾发表论文,提出用深度学习进行噪声抑制。Yong提出一种回归方法,通过学习为每个音频率生成比例掩码。生成的比例掩码完全与人声分离,并且可以删除外部噪声。虽然这种方法还不够完美,也算一个很好的基础了。
在接下来的几年时间里,很多不同方法相继出现,高级别的方法几乎相同,它们常常分为三步:
数据收集:将纯净的语音和噪音混合,生成大量合成的嘈杂数据集;
训练:将数据集输入到DNN中,得出清晰的语音输出。
推理:创建掩码,将人声与噪声分离开。
在2Hz中,我们尝试了多种DNN,最终得出了唯一的DNN架构,可以在多种场景下得出可靠的结果。平均MOS分数上升了1.4,是目前最佳成绩。
能否实现实时DNN?
延迟是实时对话中的重要问题。人类可以忍受的上限为200毫秒的延迟,否则的话就会影响通话效果。
影响端到端延迟的因素有三个:网络、计算和编解码器。通常网络延迟是主要因素。编解码器的延迟根据不同模式可能会有5—80毫秒的延迟,但是目前所用的编解码器已经非常高效了。而计算的延迟则有多方面因素。
计算延迟让DNN更具挑战性。如果你想用DNN处理每一帧,结果很可能会造成严重的延迟。计算延迟取决于以下几点因素:
计算平台的能力
我们不可能在一台头戴设备中运行大型DNN,因为有CPU和电源的限制。所以想做到实时处理非常困难,除非平台有一台加速器,可以快速进行矩阵相乘,并且还不那么费电。
DNN架构
DNN的速度取决于有多少个超参数、DNN的层数,以及节点进行的什么操作。如果你想生成高质量结果,那么DNN就不能太小。
音频采样率
DNN的表现取决于音频采样率,采样率越高,得到的超参数就越多。
如何测试噪声抑制算法?
测试声音是否得到改善也是一个难题,因为人耳很难分辨细微的差别。可是,目前也没有公开的针对噪声抑制效果的基准,所以对结果进行比较比较有挑战性。
大多数论文采用PESQ、MOS和STOI衡量结果。你提供一个原始声音音频和经过处理的音频,算法会生成一个分数。
ETSI Room
另一种更专业的发方法是进行主观音频测试,在不同标准体上测试看它们能否符合标准。
EGPP通讯组织创建了ETSI Room,如果你想将算法应用到实际中,就必须在设备中安装这一装置。
这一设置能完美地将噪声分离。它其中有一个智能机器人,内置的扬声器会模拟声音,另外在一定距离之外还有麦克风。
这一设备能让测试者用周围的扬声器模拟不同噪声,从机器人的扬声器里发出人声,最终用算法处理捕捉到的音频。这一切都能自动进行。
输出噪声和输入噪声
假设现在你正在和团队参加电话会议,总共有4人。所以潜在的噪声就有4种,每个人都有可能制造背景噪声。
传统来说,噪声抑制都在边缘设备上,也就是仅限于麦克风。你从麦克风中得到信号,一直噪声,然后对信号进行上采样。
由于单一麦克风的DNN方法只需要一个源流,你可以将它放置在任意地方。假设现在你想过滤掉麦克风的信号(输出噪声)和听到的扬声器中的信号(输入噪声)。我们创建了APP——Krisp,它可以处理两种噪声:
以下视频演示了非静止噪声是如何被DNN过滤掉的:
对输入噪声抑制来说,问题变得越来越复杂了。你需要处理算法不常见的声音和人声变体。例如,你的团队可能会用到会议设备,或者离设备距离较远。或者远程的人是从车里打的电话,带来更多环境噪声。另外,可能会有几个人同事说话的情况,这样又该怎样判定哪些是噪声呢?
有时听到手机铃声响起,他应该算是噪声还是铃声?
转向云计算
了解了噪声抑制技术所需要的条件,而算法又是完全基于软件的,那么它可以迁移到云上吗?如下图所示:
在云上进行噪声抑制有多种优点
答案是肯定的。首先,基于云的噪声抑制技术能在多种设备上运行,另外,它能进行双向甚至多向工作。在过去,这是不可能的事,因为传统方法需要多个麦克风。然而,深度学习技能支持单个麦克风,也能用云进行计算。
现在,最大的问题就是算法的可扩展性了。
GPU vs CPU
如果我们想让算法足够服务真实的因特网语音(VoIP)负载,我们就需要了解算法是如何工作的。
目前的大型VoIP设备可以支持10K—100K的流。有很多因素会影响媒体服务器可以支持的音频流,其中最主要的因素就是服务器平台。如下图所示,基于云的媒体服务器和经过优化的裸机服务器相比,裸机服务器明显胜出:
服务器必须价格实惠,才能让消费者看到优势。我们首先用CPU对2Hz做了实验,单个CPU核可以处理最多10个平行流。
之后,我们在GPU上做了实验,结果非常惊人。一个英伟达1080ti在没有优化的情况下可以扩展到1000个流,经过优化最大可以达到3000个流。
用CUDA进行批处理
让我们来研究下,为什么GPU能比CPU强这么多。
CPU供应商们一直以来将大量的时间和精力用于优化和加速单线程架构,用算法和各种技术尽可能缩短单线程的时间。因为大多数应用都只需要一个线程,所以CPU制造者只需要发展结构即可让应用发挥最大性能。
而GPU供应商需要对很多平行任务进行优化,大量平行都需要3D图形处理。
批处理(Batching)就是在GPU中平行处理的意思,你讲一批数据输入进GPU中,经过平行处理后再返回,这是音频流处理的理想工具:
这里,我们用英伟达的CUDA库直接在英伟达GPU上运行这一过程。下方的代码表示CUDA的矩阵相乘过程。
void kernelVectorMul(RealPtr dst, ConstRealPtr src1, ConstRealPtr src2, constsize_t n)
{
constsize_t i = threadIdx.x + blockIdx.x * blockDim.x;
if (i < n)
dst[i] = src1[i] * src2[i];
}
voidUtils::vectorMul(RealPtr dst, ConstRealPtr src1, ConstRealPtr src2, constsize_t n)
{
dim3 gridSize(n / getDeviceMaxThreadsX() + 1, 1, 1);
dim3 blockSize(getDeviceMaxThreadsX(), 1, 1);
kernelVectorMul <<< gridSize, blockSize >>> (dst, src1, src2, n);
}
voidUtils::vectorMul(Vector& dst, constVector& src1, constVector& src2)
{
vectorMul(dst.getData(), src1.getData(), src2.getData(), dst.getSize());
}
voidUtils::matrixMulRowByRow(Matrix& dst, constMatrix& src1, constMatrix& src2)
{
vectorMul(dst.getData(), src1.getData(), src2.getData(), dst.getSize());
}
下面是用CUDA进行快速傅里叶变换的过程。
FFT::StatusType FFT::computeBackwardBatched(ComplexTypePtr src, RealTypePtr dst)
{
StatusType s = cufftExecC2R(backward_handle_, reinterpret_cast
dim3 gridSize((getBatchSize() * getForwardDataSize()) / thr_max_ + 1, 1, 1);
dim3 blockSize(thr_max_, 1, 1);
float val = getForwardDataSize();
kernelDivide <<< gridSize, blockSize >>> (dst, val, getBatchSize() * getForwardDataSize());
return s;
}
FFT::StatusType FFT::computeBackwardBatched(ComplexVector& src, Vector& dst)
{
return computeBackwardBatched(src.getData(), dst.getData());
}
-
英伟达
+关注
关注
22文章
3740浏览量
90802 -
深度学习
+关注
关注
73文章
5492浏览量
120962
原文标题:英伟达用深度学习消除背景噪声
文章出处:【微信号:jqr_AI,微信公众号:论智】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论