查看原文
其他

Unite 2017 | Unity中可用于VR环境的空间化音效

2017-06-14 孙志鹏 Unity官方平台

空间化音效对于营造游戏沉浸感来说至关重要,而VR环境对于音效的要求则更为严苛。在Unite 2017 Shanghai的VR/AR专场,Unity技术支持工程师孙志鹏为大家分享了如何在Unity中实现可用于VR环境的空间化音效,今天这篇文章就来一起回顾当时的内容。

 

人类的听觉系统


首先来分析一下人类是如何定位空间中某个声音的位置的,这个过程可以分为两个方面,确定方向和确定距离。


确定方向

确定方向无非就是确定左-右-前-后-和对应的仰角。其中确定左右主要靠ITD(时间差)和ILD(强度差)这两个参数, 根据头部尺寸大小进行设置。这里有一对经验值,对于800Hz以下的声音主要靠时间差来确定左右方向,高于1500Hz的声音则主要靠强度差,频率在这之间的声音则由二者共同决定。对于前后关系和仰角就需要交给HRTF(头部相关传输函数)了。当然我们有时也会“侧耳倾听”换个角度来把前后的问题转换为左右的问题。值得一提的是,对于前方的音源,我们的听觉系统可以做到1度左右的精确度,对于两侧的音源可以有15度左右的精确度,而且我们能分辨10毫秒内的时间差。 


下面来看看ITD(时间差)和ILD(强度差)的影响权重是如何与人的头部尺寸相关的,之前提到过800Hz以下的声音就只能看时间差来分辨左右了,以图中200Hz的声音为例,声音的半波长大约是85cm,远大于我们正常人类的头部尺寸。在这个情况下根本无法挡住声音,所以声音的强度差显然靠不住了。而在高于1500Hz的6000Hz声音的情况下,我们会完全挡住声音,所以无法靠时间差而只能依赖于强度差,而对于前/后和仰角就交给HRTF吧。


确定距离

在距离方面,对于熟悉的声音,及我们知道何为大声与小声的声音,当然是声音越大离我们越近。对于表示直接声音和经过一次反射的声音到达耳朵的延迟的Initial Time Delay来说,当然是延迟越大,说明音源离我们越近。对于我们听到的直接声音和反射声音的比例来说,当然是直接声音的比例约高,音源离我们越近。对于听觉的运动视差来说,越近的声音运动频率越快,想象我们站在铁路边,一辆火车以恒定的速度从远处开来。我们听到火车的声音由远及近时,一开始声音移动地很慢,可到了近处时火车呼啸而过,声音移动地很快。高频声音在传播的过程中会比低频声音衰减的更快。所以高频部分衰减的越少说明音源越近。


相对于传统的7.1和5.1声道的环绕立体声来说,环绕立体声依赖于一个固定的布置和对听者位置和朝向的假设。这样的限制显然不适合于虚拟现实环境下的使用场景,因为玩家可能需要环顾四周甚至走来走去。


那么在知道了人类时如何定位一个3D空间的音源后,3D音源的空间化实际上就是对上述过程的一个逆转过程,简单来说,我们要做的就是处理声音,让它听起来像是在空间中我们所设定的位置发声。那就需要从方向和距离两个方面来进行处理。方向上主要依靠HRTF加上头部跟踪来处理,距离上则是利用刚才所讨论的声音在距离上的相关特性来逐一处理。


HRTF的概念


首先需要明白什么是HRTF,但是在介绍HRTF之前,有必要先解释一下什么是HRIR(头部相关的脉冲响应)。HRIR是一个与音源和耳朵位置相关的脉冲响应,对任意音源做某一特定HRIR(头部相关的脉冲响应)的卷积就是把该声音处理成,让耳朵听起来像是音源在这个HRIR相关联位置发出声音的过程。


上面介绍了HRIR的概念,而HRTF就是它的傅立叶变换。傅立叶变换可以把卷积变成乘法,乘法变成卷积。这里我们显然希望使用乘法来代替卷积运算从而减小性能的开销。所以我们需要HRTF。


再来进一步解释HRTF。HRTF是因为散射导致基于音源位置来选择性加强或衰减某些特定频率的现象。耳朵在这个过程中扮演了一个声音探针的角色。这个效果可以在数十分贝的数量级上影响某些特定频率声音的大小。


上图可以让我们对HRTF有更直观的认识。这个图是来自正前方仰角15度的一个HRTF,其中横轴是频率,纵轴是加强的分贝数,绿色的曲线代表左耳,蓝色的曲线代表右耳。值得一提的是几乎每个人的HRTF都因为不同的头部大小、不尽相同的身材和独特的耳部生物特征,而成为独一无二的个人属性。

 

HRTF的原理


在了解什么是HRTF后,下面来看看HRTF是怎么来的,测量HRTF的机构有很多,这里列出来wiki上能搜到的一些,我们可以看到大致方式就是在一个不会产生声音反射的房间用一圈喇叭对一个人体模型发声,并在耳朵处装有接收记录的装置。可以想象测出来的数据是一个以听者为球心的球面数据。需要我们用方位角和仰角去索引出某个我们想模拟的角度所对应的HRTF。


现在来看看HRTF是如何作用于声音的传播过程的。假设空间中特定位置的扩音器发出的声音为X1,X1经过扩音器的Transfer Function传播到听者所在的位置。然后经过由人体特征构成的天然滤波器HRTF到鼓膜被我们听到,假设再用一个麦克风把听到的声音记录下来为Y1,那么如果想在耳机里直接模拟出这个过程,就需要有一个Transfer Function涵盖LF/H的整个过程,最后同样在鼓膜里听到的Y2和之前的Y1完全一样。


在这个过程中,因为HRTF和代表声音在空间中的传播过程的L都是由听者和音源位置来共同决定的,所以我们的头部追踪和场景更新也需要在这个过程中更新L和F相关的参数。 


在关于距离的建模里,都是一些非常好理解的物理事实,声音从远到近,会因为距离而衰减。直接声音和初次反射声音的时间差,从远到近,会由小到大。直接声音和反射声音的比例,从远到近,直接的声音的比例也会逐渐增高。从声音的移动上来说,正如之前讲到火车的例子,从远到近,音源的移动速度也会由慢到快。从高频声音的衰减来说,我们需要在考虑声音基于距离衰减的基础上,让高频声音衰减得更快一些。


Unity中实现空间化音效


现在已经了解如何在耳机里模拟空间中特定位置的声音了。下面看看这个过程如何在Unity里快速实现。Unity为开发者们提供了一个空间化音效SDK,要讨论这个SDK就不得不提到Unity的Native Audio Plugin SDK,因为它是Unity空间化音效SDK的基础,Unity中的任意Audio Effect都可以用这个SDK完成,它可以像Graph一样去构建复杂的音效。比如输入两个音源来实现混音效果。它为我们提供了一套回调函数,其中最关键的就是ProcessCallback这个函数,让开发者可以在这里对音源的每个Channel每个Sample进行处理。


在Native Audio Plugin SDK的基础上认识一下Spatialization Audio SDK,并了解如何在这个SDK的框架下实现空间化音效。相比Native Audio Plugin SDK,Spatialization Audio SDK唯一的区别是在整个声音特效的Graph里,一旦指定了某个音效是空间化音效,那么对于每个启用了空间化的音源来说,都有一个空间化音效的Instance在Graph里与之相连。接下来进入具体的实现环节。

 

空间化音效

首先是Capturing HRTF,当然也可以选择不用自己Capture,而使用一些现成的数据,刚才我们已经列举了一些可以下载带现成数据的地方。在Unity提供的Sample里,我们使用的是MIT EDU提供的数据,其数据结构是这样的,有14个仰角,对于每个仰角有一定数量的方位角,从水平向下40度直到头顶90度的一个不完整的球面范围,它的音源半径是1.4m。


然后来讨论一下在SDK里应用HRTF的过程,主要就是在ProcessCallback里,根据方位角和仰角找到对应的HRTF,因为音源里的Sample Data是一个时域空间的信号,我们刚才也解释过时域空间需要做卷积,所以使用快速傅立叶变换将时域空间的离散信号(数字信号)转化到频域空间,这样就可以用复数乘法代替卷积运算,以减少性能的开销。在处理完对特定频率的增强和衰减以后。我们再把Audio Data转回时域空间,写入这个Audio Effect的Output Buffer。整个操作完成。

 

但这个过程中的计算量仍然不小。且像这样的没有太多逻辑关系的纯计算任务也比较适合在GPU上完成。所以现在的一些GPU厂商也相继为这样的需求提供GPU的硬件加速支持。比如AMD的TrueAudio Next,就提供了一套与Unity Audio SDK里很相似的API来做傅立叶变换和复数乘法,甚至也有卷积运算的函数。让我们可以很容易的集成使用并能获得 GPU的硬件加速的运算能力。


 

然后在Head Tracking的部分我们需要将头显的方位数据应用到场景当中带有Audio Listener这个组件的Camera上,使得我们在ProcessCallback 里拿到的Listener Matrix正好就代表头显的位置矩阵。而这个过程在Unity里是自动完成的。当启用了VR支持后主Camera就会自动多出VR相关的属性。也会自动完成这个关联的过程。

 

音效距离建模

在方向的空间化之后,接着来看看距离方面,对于声音的衰减和声源的移动来说,可以在CreateCallback里注册一个距离相关的衰减回调,然后在这个回调函数里可以计算一些距离相关的衰减并把它应用到音源数据上。


对于Initial Time Delay 和 Direct/ Reflection ratio这两个方面,牵涉到声音在场景中的反射。即牵涉到了复杂的三维场景,显然计算量相当巨大。但其实可以用一个Cube来近似取代3D场景。这样就可以大大简化这个计算过程。所以可以在Create Callback里创建注册一些描述这个近似模拟场景的Cude的长宽高属性,然后Unity可以自动生成相应的UI让Audio Effect使用者来做调整。然后可以在ProcessCallback里根据这些数据来计算反射。


对于高频的衰减来说,可以在之前HRTF的处理过程中,当音源数据被换到频域空间后添加一个频率相关的基于距离的衰减。


讲到这里也许还是会有人觉得自己开发一个空间化音效太过复杂,其实Unity里也有现成的空间化音效插件,例如由Oculus提供的Unity 插件,是一个硬件无关的实现,也就是说它也可以用在Oculus之外的VR硬件上。当然大家也可以基于我们的NativeAudioPlugins的例子进行开发,来增加一些定制化的功能。


更多Unity相关技术文章

Unity 5.6中的混合光照

Unity结合Vuforia开发AR应用

Unity实验预览版支持为macOS开发VR及AR内容

基于Animation Instancing的大规模人群模拟

eaglEEye性能测试平台详解


Unity官方活动


2017 Unity技术路演华东区(上海、南京、杭州)现已正式开启报名!在这个夏天,感受来自Unity官方技术团队的热情!


点击“阅读原文”报名Unity技术路演

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存