前言
我是一名在心动网络从事音频相关工作的技术人员,有的人称我们为音频程序员,有的人称我们为技术音频,也有的称我们为TA(Tech Audio)。这些对我来说,没有明显的不同——说到底,我们的存在都是为了解决项目中声音方面的问题,在尽可能满足声音设计师需求的同时,提升声音的生产效率及其在游戏中的使用表现。今天,我想站在一个技术的视角,与大家分享声音在游戏引擎中的工作原理与优化思路,以下都是个人之见,如果有说的不对或者模糊的地方,欢迎随时私信与我交流。
0
首先,我想谈一谈声音,什么是声音,这个词对我们来说熟悉又陌生——熟悉,因为我们几乎每时每刻都在与它打交道,当你用键盘打字,与人沟通,都会发出声音;陌生,是因为我们很难用简要的文字去描述声音到底是什么。
图1 什么是声音
在我的理解中,声音的本质是振动,声源运动对空气分子产生挤压,使其形成疏密相间的纵波,纵波以声源为中心向外逐渐扩散并逐渐衰减,直至彻底消失。在这个过程中,若震动被我们的耳朵捕获,由外耳道到达鼓膜,振动传播介质转换为固体,进而传达至听神经,最后以神经脉冲的形式到达我们的大脑,并经由大脑对信息的处理、统合,形成听觉。
图2 声音通过人耳传达至大脑
对人类来说,并不是所有频段的声音都能被感知到,一般情况下,人耳可以识别的声音频段处于20 – 20000Hz之间,不排除有些人可以听到这个频段以外的声音,人耳对于2000Hz至5000Hz的频率最敏感,在此频段之下或之上,便需要更高的声强才能产生相同的“响度”感知。说到频段,不得不提到一个名词,分贝,它是一个对数单位,用于表示两值之比,通常我们习惯用分贝(dB)来描述声音强弱,当然我们也可以使用帕斯卡,前者是声压级的测量单位,后者是声压的测量单位,从某种程度上来说,使用分贝可以更方便对声音的强弱进行观测,本质并没有区别。
图3 等响曲线图
简单了解了什么是声音之后,我们再来看一下它在空气中传播的一些规律,以点声源为例,我会将它归纳为吸收、反射与衍射三种。
声音的吸收,指点声源是呈球形扩散,在传播过程中,遇到物体表面后部分被吸收。
图4 声音传播到达障壁发生吸收与反射
此外,在空间中的传播受到大气的吸收也会导致其能量产生衰减,但是大气的吸收对声音整个频段的影响不是均匀的,越高的频率受到吸收的效果越大。这也是为什么,远处的声音往往听起来更低沉浑浊,近处的更丰富饱满。
声音的反射,当传播遇到物体表面以后,部分声音被吸收,一部分声音将被反射,如果声音发出后直接到达聆听者,我们称作直达声。 当声音发出后并非直接到达聆听者,而是经过物体表面部分吸收之后,经一到两次反射到达聆听者的声音,我们称之为早期反射,早期反射的时间范围通常是取直达声以后50ms-100ms;声音发出后,经过表面反射数次,主要指早期反射之后的反射声,相互干涉后再到达聆听者的声音,为后期反射,也叫后期混响。这里再介绍两个在录音行业出现频率比较高的名词,干声与湿声,其中,干声是指从拾音设备到声音记录设备的原始声音信号,中间没有经过任何后期处理(如添加混响效果器等)或硬件串联;湿声是指从拾音设备到声音记录设备的过程中,经过后期处理或串联了其他设备得到的声音信号。
图5 直达声、早期反射、后期反射
声音的衍射,是指当声音在传播过程中遇到障碍物或空隙时,传播方向发生变化而绕过障碍物的一种现象。
图6 声音的衍射
除了声音在传播中会发生吸收、反射、衍射等现象,声音与声音之间会出现相位干涉,多种声波发生重叠时,同频段的声音波幅会发生叠加。简单解释一下,相位是指声波在它的一个周期里某一时刻所在的位置,拿最容易理解的正弦波举例,现在有两个频率一样、振幅相同的正弦波,如果它们相位处处一致,那么它们叠加后的声波振幅会得到加强,声音听起来变得更响;如果它们相位处处相反,由于它们频率与振幅相同,叠加后彼此抵消,声音被消除;最后一种情况是相位干涉,如果它们相位既不完全相同,也不完全相反,这种情况下,在同频段的波幅会发声叠加。
图7 同相、异相、相位干涉
我们一般在搭建录音棚时,经常需要考虑到用不规则的表面以及吸音性能良好的材质来进行内壁的设计,这是为了防止声音经过反射与原来的声波相互干涉,产生驻波或梳妆滤波现象,影响室内采集的效果及聆听者的听感体验。
图8 录音棚图示
此外,我们所使用的降噪耳机,也是使用声音之间相互干涉的特性,制造一种与环境噪声相位相反,频率、波幅相同的声波与其相互抵消。
图9 降噪
讲完静止的声源,我们再来看看动态的声源,当声源与聆听者都处于相互运动的状态时,聆听者接收到的波的频率与声源实际发出的频率是不相同的,这种现象,我们称之为多普勒效应。在日常生活中,多普勒效应随处可见:当汽车从远处驶过来,由于波长相对变短,频率变高;反之则由于波长相对变长,频率降低。
图10 多普勒效应图示
1
前面我们介绍了声音在自然界中的一些特性,那么游戏中的声音又是什么呢?当我们将采集到的声音信号制作成声音资源,放到游戏里,它尚不具备在自然界中声音的全部特性,这个时候我们需要声音引擎——通常在游戏追求声音表现的真实性时,它的职责是在人耳可感知的范围内,尽可能对声音在自然界中的听感进行还原。那么游戏中的声音引擎,到底做了些什么?
图11
首先是声音的生成与播放,我们游戏的声音资源哪里来——由设计师进行采集加工制作而成。放到游戏中以后,它虽然只是一个的音频文件,但是本质上,它代表着这个声音样本的最高品质,后期的一切处理都是对它的约束与限制。声音引擎在这个阶段要做的就是当在游戏中触发了某些事件以后,生成这些事件对应的声音,过程包括解码、渲染声音,或是通过DSP算法实时合成出声音。
解决了基本发声问题以后,我们便需要开始关注声音的空间定位——我们不仅要它有声音,还想知道它离我们有多远,在我们左边还是右边,上面还是下面。这个时候声音引擎它就负责制造这种幻觉——令每一个3D虚拟声音对象对聆听者而言都好像是来自游戏世界里对应位置。首先,关于游戏声源远近的实现,声音引擎通过控制每个声源到最终扬声器上的音量大小和频率响应,来描述游戏声源与聆听者的径向距离关系;然后,关于游戏声源水平方位上的实现,拿5.1声道来举例,通过控制游戏声源在不同扬声器中的相对音量与频率响应,再结合声音由扬声器发出后到达人左右耳的时间差(ITD)与响度差(ILD),让我们产生一种声源存在于扬声器之间的错觉;随着现代技术的进步,现在我们可以通过结合Ambisonics及头相关函数(HRTF),来计算人耳对不同高度的游戏声源的频率响应,以此描述游戏声源在垂直维度与聆听者的关系,让空间声源的表现变得更加精准与丰富。
图12 虚拟声源
图13 支持垂直维度声音表现的杜比全景环绕声
声音的基本空间感建立完成后,我们还需要考虑,当游戏世界中,“声源与聆听者之间有一面墙”,或者“声源与聆听者都在一个房间里”等复杂的情况,声音该如何表现——我们需要进行声学建模。声音引擎允许通过模仿声音在聆听空间的早期反射和后期混响特性,以及模仿声源和聆听者之间因障碍物造成部分或全部遮挡的情况,来提高声音和场景渲染的真实性。想象一下,一个点声源,向四周发射若干条射线,通过计算射线与其他表面碰撞的反射来确定最终渲染出的混响声。那么如果场景有若干个点声源,还需要考虑它们之间的相互干涉,射线反射到平面的次数,再与反射后的声波进行干涉,这样的“暴力声学模拟计算”量将非常庞大。通常在游戏中进行类似的声学空间塑造时我们都会采取更讨巧的方法,实际上有非常大的可优化空间。但类似纯物理模拟式的工作方式在声音引擎中是可行的,只有当你真正需要的时候,再考虑使用。
图14 声学建模图示
既然自然界的声音存在多普勒偏移,我们的游戏世界自然也少不了这个老朋友。在现实世界中,声音的多普勒偏移受制于真实物理环境,声音在空气介质中拥有自己的速度,然而到了游戏世界里,当声音事件触发以后,引擎需要通过聆听者与发声体的位置变化,计算出聆听者与发声体之间的相对速度,再分别乘以一个多普勒系数(它主要是对聆听者与发声体之间相对速度进行放缩,通常这个系数是1),然后各自加上声音在空气中的传播速度(一般取343.3m/s),最后将它们得到的结果相除,根据得到的比值来决定最终的音高变化,这里我们不展开讨论,感兴趣的小伙伴可以网上查阅相关资料。
最后一步,混音,也是最重要的一步。
图15
在我们所有的声音资源都到位并正确配置进游戏以后,我们还需要真正进入游戏去体验,在我们制作单一的声音资源时,我们往往会忽略这个声音的整体性,单听一个怪物的声音,也许不会发现有什么不妥,当这样的怪物成群结队出现以后,声音的感觉也许完全不同,同时,这些声音与其他音效,诸如角色的语音、环境音效、背景音乐该怎么配合,才可以让他们都听起来井然有序,这些都是设计师在混音阶段该考虑的事情——对于声音引擎来说,该如何管理、控制游戏中所有的2D(音乐,语音)与3D声音(环境、特效、动作)的相对音量。当然,混音的程度一部分是由游戏的物理环境所驱动,另一部分是由声音设计师的审美来决定。这种审美是主观的,对于横版格斗游戏来说,当你和对手距离拉开时,我们的摄像机机位(聆听者)也会随之拉远,此时距离加大,游戏的场景会更完整的呈现在玩家眼前,由于聆听者与声源距离更远了,声音应当变得更轻,更浑浊,然而考虑到画面整体表现,也许设计师并不会这么做, 相反的,他们会利用这种距离上的衰减,对音量进行反增益,让背景环境声变得更响,从而更好的表现场面的恢弘,因为他们希望此时的玩家把更多的注意力放在场景上,而非角色本身。
2
随着游戏行业的发展,声音越来越受到大家的重视,玩家对于游戏的声音要求,已不仅是有和无,而是如何打到更好的听觉体验。也有越来越多的游戏公司,从原来把声音工作全部外包,到项目组开始拥有自己的声音设计师,再到成立音频小组,甚至音频中台。对于开发者来说,如何在游戏中以最少的资源实现最好的声音表现,是我们应该思考的问题。这次的优化分享,主要还是基于当下一款比较流行的声音中间件Wwise(在Unity中取代原生声音引擎)在Unity引擎中的优化思路。
图16 Wwise中间件
个人认为声音的优化阶段一般发生在项目的中后期,我们之前已经提到,声音资源由设计师制作完成的那一刻起,就已经决定声音在游戏中的最高品质,后续产生的优化行为全部都是在对声音的品质与性能做取舍。因此,从整体的声音设计思路来看,在前期,不主张对声音资源的包体和声源实例数进行干预,目的是为了尽可能在开发前期,营造一个完整的声音生态,到了中后期或者版本的结点,可以考虑对声音设计做减法,这样也是为了让设计师对游戏的整体声音有更好的把控。
所有优化的第一步,了解游戏声音资源的用量,你可以通过很多方式了解资源用量,这里比较好用的性能检查工具推荐Wwise中间件的Profiler,它可以最直观了解声音性能的瓶颈在哪里,如果条件允许,也比较推荐在游戏客户端实现一套针对声音性能的分析工具。
图17 Wwise Profiler界面(部分)
Wwise还提供了非常强大的Query功能,你可以利用它在Wwise工程中找到几乎你能想象得到的所有Wwise对象,查找条件可以具体到某一个对象身上的某一个属性参数,甚至某一种编码器下的具体采样率,而且你可以随意设计并保存你的Query逻辑,不仅如此,除了帮你将符合条件的结果找到以外,你可以直接在结果中对它们进行编辑和修改。
图18 Wwise Query Editor
这样不仅可以大大提高设计师的排查效率,也降低了声音设计师以外的小伙伴使用Wwise的门槛——即便你不是一个Sound Designer,你依然可以轻松使用Wwise来监控与优化游戏的声音表现。在大多数时候,关心声音性能的不仅仅是设计师,还有程序,策划。凡是使用Wwise作为声音引擎的游戏项目,还是强烈推荐大家下载和使用Wwise的编辑器来监控和优化声音。
声音的优化主要可以分为内存与CPU两大块。 先来看看内存方面的优化——在完成Wwise工程以后,所有必要的信息都会打包到一系列的Soundbank中,包括声音片段媒体,声音的事件以及所对应的声音对象结构信息等——合理分配Soundbank的粒度,为后续客户端资源加载做准备很重要。项目前期我们会把声音事件与资源按游戏中的类别来进行分类管理,到了游戏中后期,在这一基础上,我们会进一步分离同一个Soundbank中常用声音事件与不常用声音事件:拿角色语音举例,某一角色ta的语音bank里共有50句话,其中30句出现的频率比较小(某些剧情对话或与特殊NPC对话时出现),剩下20句出现的频率比较高(比如战斗挥砍或技能、看板娘日常语音等),我们会考虑进一步对其bank进行拆分,因为它们存在于内存中的时间长短不同,减少频繁加载的机会,这样可以减少内存中多余的Soundbank的占用。
一般我们对游戏音乐的品质要求相对较高,设计师在制作音乐资源时,一般也会采用较少的压缩以保证音乐的完整性与保真度。少量压缩会导致音乐资源的体积相对较大, 当声音引擎直接加载使用时,占用的内存也相对较大。针对音乐的播放,我们会采用流播放的形式,流播放是指媒体数据在播放前并不会被整个加载到内存,只将开始部分的内容载入内存,后续过程中CPU数对数据包进行缓存并使媒体数据正确的输出。它的缺点是从声音事件调用时算起,到声音渲染出之前可能会有一定的延时,这是因为引擎需要花费一些时间来定位这个媒体并启动流播放,大多数情况下,这种延时几乎感觉不到。此外,Wwise也提供了针对延迟的解决方案,这里主要介绍它的Zero latency和Prefetch length功能,当你在Wwise编辑器中勾选了Zero latency选项,这意味着该声音文件的开头一部分数据会被打进它所在的Soundbank,这部分数据的大小取决于Prefetch length这个参数的设置(单位是毫秒),当游戏中的声音事件被调用时,引擎会直接从Soundbank中的预取数据开始播放。
音频编码格式的选取也非常重要,现代科技对音频的编码算法已经非常成熟,无论是针对语音、音效、音乐都有非常灵活的编码器选择。Wwise提供一些常用的编码器,针对不同的情况,都有比较合适的解决方案。这里主要介绍三种格式:
- PCM,它是一种未压缩的格式,所占用的CPU是最小的,取而代之的是此格式的文件会占用大量的空间,这种格式的音频适用在一些非常短的、高频触发的声音;
- ADPCM,与PCM相比,它的压缩比是3:1,虽然CPU占用要比PCM略高,但是与其他格式编码器相比,CPU消耗几乎无增长,在移动端上,如果你对音质要求较高或者是对低延迟有要求的场合,但是又不希望太占内存,推荐使用ADPCM;
- Vorbis,推荐它是因为它是互动音频行业最常用的音频解码器,它的优势是可以用很低的比特率下还原出比较高品质的声音,它的应用环境与之前PCM的相反,对其压缩后进行解码需要消耗一定的CPU资源,但体积相对小非常多用在高频触发的声音上时要谨慎;
除此之外,Wwise还提供了Opus,AAC等编码格式,感兴趣的朋友可以自行了解,选择并不唯一,具体情况还是要具体分析。
除了编码格式,我们还要考虑编码器下的采样率参数,采样率越高,还原出来的声音与原始声音信号越接近,但是相对来说,压缩后的声音文件也就越大,这里面就不得不提到奈奎斯特采样定律——它是指当采样频率大于信号中最高频率的2倍时,采样之后的数字信号完整地保留了原始信号中的信息。如果我们刻意地使用低于奈奎斯特采样定律的采样率对该声音文件进行转码,可能产生混叠现象,导致音质变差,样本的高频消失(被还原成低频)。一般的,我们针对人声,会采用较低的采样率进行压缩。
图19 信号混叠失真
声道数也是资源制作时需要考虑的一个因素,双声道的体积一定是单声道的两倍,因为双声道的声音发送到左右两个扬声器的信号是不同的。
除此之外,在业务逻辑层面的优化,Wwise提供了一些解决方案,你只需使用AkBank组件中的Save decoded bank选项,当对Soundbank解码时,它会将解码后的Soundbank资源保存在本地DecodedBanks文件夹中,以便下次加载时,不用额外对资源进行解码,这种方法对使用了Vorbis高压缩的编码格式效果显著,前提是对游戏解包安装后的本地存储容量无要求。
图20 Wwise编码格式图示
以上是针对声音内存优化的一些方向,接下来我们再看看CPU方面的一些优化思路,首先还是编码格式,对编码格式的选择其实就是在对时间和空间的博弈,如果选择压缩比较高的编码器,得到的资源体积会小(空间),但是解码消耗的CPU(时间)就会上去,相反,如果选择压缩较小的编码器,资源占用体积就会变大,CPU消耗就会减少。具体选择哪一种,还是根据游戏的实际情况来判断。
虚声部系统是Wwise中间件强大的功能之一,设计师通过对声音参数的控制,比如电平阈值,最大实例数以及声音对象的优先级来动态管理声音与声音之间内部逻辑关系,当游戏中的声音音量电平达到设计师设置的阈值,或者声源的发声数量达到了数量限制,系统会按照设计师的要求对声音进行虚声部管理。它的好处是可以自动化管理声音与声音之间的关系,处于虚声部队列的声音不会被声卡渲染,也就降低了CPU的消耗。虚声部系统灵活且强大,伴随而来的是它也要求设计师非常仔细,如何与游戏体系中的发声体很好的契合是一个需要反复调试的过程。
前文有提到,在制作声音时,设计师有时会选择使用一些效果器,来丰富声音的表现——比如,当玩家与声源处于一个封闭空间时,通常我们会在与玩家所在空间相关的Aux bus上添加Reverb效果器,为这个空间里的声音实时添加混响效果,从而大大提高临场感,但这也对应着一定的CPU消耗。个人还是非常支持设计师在游戏中适当地使用一些提升听感体验的效果器,如果达到性能瓶颈,建议优先考虑编码格式方面的优化,迫不得已要进行效果器的减法,建议结合使用profiler来平衡取舍,因为通常解码带来的消耗要比效果器带来的多。
最后就是针对业务逻辑层面的CPU优化,在游戏中,尽量避免不必要的声源调用,如果是一些不规则的发声体,比如河流小溪,可以考虑使用动态声源点,不在可听范围内的声音尽可能不去渲染,严格管理发声源。
以上是我对声音优化的一些个人看法,说得比较啰嗦,感兴趣的小伙伴可以一起交流,游戏的表现千变万化,合理的分配资源,利用好现有的工具,找到问题所在,对症下药才是关键。
评论