音频混成器概述

概述用于播放游戏内音效的音频系统。

Choose your operating system:

Windows

macOS

Linux

音频混成器是一款使用自身模块的多平台音频渲染器。它支持跨所有平台的功能对等性,向后兼容大部分旧有音频引擎功能,并将UE4功能扩展至新的域。本文档介绍音频混成器的整体结构,并提供参考点供进一步讨论。

背景和动机

音频渲染

音频渲染流程:解码并混合声源,馈送至音频音频硬件终端(也称数模转换器或DAC),最终在一个或多个扬声器上播放。各种音频渲染器的架构和功能集彼此间差别很大,但对于重视交互性和实时性能特征的游戏来说,必须支持实时解码、音效参数的动态消耗和处理、实时采样率转换,和各种其他音频渲染功能,如每源数字信号处理(DSP)效果、空间化、子混音、后期混合DSP效果(例如混响)。

平台级功能:音频渲染API

通常,每个硬件平台提供至少一个全功能高级音频渲染C++ API。某些平台提供多个选项。这些API通常提供平台特定的编码解码器和平台特定的编码器和解码器API。很多平台提供硬件解码器,以提高运行时性能。除编码解码器以外,平台音频API提供音频引擎可能需要的所有其他功能,包括音量控制、音调控制(实时采样率转换)、空间化和DSP处理。

游戏级功能:游戏API

游戏引擎基于这些平台级功能编写其他功能。例如,功能可能涉及脚本引擎(如蓝图)或游戏特定的组件和系统(如音频组件、环境Actor和音量),或做大量的工作来确定实际播放的音效(如并发音效)以及使用的参数(如音效类、音效混合和声音提示)。

平台特定的音频渲染API的问题

当要支持的目标平台较少,且新平台交付期较长,则此模式很有效。但是,若使用支持大量平台的UE4,力图兼顾各平台特定的API之间的差异,猎取平台特定的漏洞,并努力实现平台功能的对等,这些会轻易占据音频引擎的大部分开发时间。其代价是要编写新的运行时功能或开发工具。

由于此范例中无法实现功能对等,因此需要创建和维护功能支持矩阵,与质量保证团队和音效设计人员就哪些功能适用于哪些平台进行沟通。与此相关的文档和支持都很难提供,因为并非所有功能都适用于各个平台。在并非所有功能都适用于各个平台,且现有功能在不同平台的效果也有所不同的情况下,混合一款要在多个平台上发行的游戏是很困难的。

编写新的音频渲染级功能是需要逐个平台单独实现的,否则会增加平台差异问题。同样,凡涉及到优化或修复漏洞,要么需要复制,要么需单独针对特定平台。

通常,新的低级功能、优化和漏洞修复是不可行的。若某平台API存在性能问题或已知的漏洞,除了与平台所有者合作,通常无其他补救之法。漏洞修复通常由破解或变通方法组成。即使新功能可行,通常也会降级至某个窄平台插件API,不会用于多个平台。

在新平台上实现平台特定的音频API需要做大量工作,并且需要更长的开发周期。某些情况下,全新的平台甚至没有全功能的音频API。这种情况下,在平台投入资源编写自己的音频渲染API之前,根本不可能在该平台上建立音频渲染。

任何游戏引擎都有一条令人兴奋的出路,即第三方可向UE4添加新功能和扩展。由于平台API非常复杂,而且自身可能有多种方式支持插件扩展,创建普适性的通用API几乎毫无可能。

解决方案是音频混成器

解决所有这些问题的办法是单个的多平台音频渲染API,即所谓的音频混成器。使用音频混音器时,由于所有平台都有一个通用的代码库,因此功能对等较容易实现。由于程序员可一次实现一个可适用于所有平台的功能,因此开发时间缩短了。测试、文档和音效设计人员的实现及混合也简化了。除一些无法避免的特定情况外,所有平台上的东西听起来一样,做起来也一样。

支持新平台很快,一般只需花几天时间写上几百行代码就行。为音频引擎插件编写接口不仅可行,还是主要的创新途径。此外,修复漏洞和优化代码可惠及所有平台。

每个平台有不同的CPU和内存功能,或者不同的硬件支持选项,这仍是平台特有的挑战。但是,在CPU或内存不足的情况下,音频混频器可采用自动减轻CPU负载(通过禁用功能、降低质量等)或内存负载(在烘焙时清除内存、自动下采样和降低编码质量)的功能。音效设计人员和音频程序员可调优音频混成器,达成针对给定平台设定的性能和内存目标。

为何称作音频混成器

音频渲染 也称 音频混合 。由于 渲染 一词在UE4中几乎专门针对图形,因此我们决定将新的音频渲染器称为 音频混成器 。但由于 混合 一词有歧义,这一决定有时会在音频社区和其他地方造成混淆。它会与音量(响度)混合操作混淆。

UE4音频混成器 的作用基本上与硬件混合控制台相同,通过各种参数和音效处理器(包括子混音处理器和主音效处理器)处理声源,然后将这些声源添加在一起。

音频混成器架构

平台层

音频混成器有一个最小平台特定API层。平台API封装了访问各种平台的音频硬件所需的所有必要详情,该层处理查询硬件功能,并按需更改硬件状态,以及设置多平台音频混成器以将音频提供给硬件。

某些平台需要额外代码来处理平台间的各种细微差别,如状态中断、应用程序暂停、设备交换等;而其他情况下,则添加支持以利用平台特定的增强功能,如硬件加速解码。此类情况下,可能仍需大量平台特定的代码。注意,此平台特定层还可处理UE4中其他一些平台特定功能,如为各种编解码器创建运行时解码器。

缓冲区生成

不同平台用不同方式向硬件馈送音频。某些平台API会将音频以队列形式 推送 到硬件,由客户端应用程序负责排好音频的队列。其他API都基于回调,当硬件需要更多音频时,会调用客户端代码。这两种情况下,音频混成器都采用多缓冲区方案,在硬件渲染当前缓冲区(例如正在监听的缓冲器)时生成未来的音频缓冲区。

若音频混成器渲染下一个音频缓冲区时耗时过长,且缓冲区队列 匮乏 (用于推送API),或API回调时无可用音频(用于回调API),则播放时会出现明显的间隔。这称为 欠载 (有时也叫 匮乏 ),应不惜任何代价避免这种情况,因为音效非常差。欠载会导致音频流突然中断,这被视为突发噪声 - 短时间欠载会发出爆裂声,短时间内持续欠载会产生声音卡顿,长时间欠载会出现严重的音频漏码。振幅突然变化甚至会对音频接收器或扬声器造成损害。大部分情况下,欠载是因为CPU利用率达到了饱和,即因为音频混成器在有限时间内工作量太大。其他情况下,欠载可能表示UE4任务图(用于异步解码或合成)中出现阻塞,或其他一些问题。有时也很难区分音频中因欠载而产生的咔哒声或爆裂声,反之亦然。

另一方面,也有可能是预先生成的音频过多。此类情况下,游戏事件会越来越滞后于实时状况,这就被视为延迟。极端情况下,这被称为 过载 ,这也是要避免的。实时音频引擎需要找到欠载与过载之间的平衡点。欠载无论如何要避免,而过载,某种程度上可用于避免欠载,但需要低于感知阈值。

寻找适当的平衡点不太容易,通常依平台而定。为此,利用音频混成器,音效设计人员(音频程序员)每次执行音频缓冲区渲染时都可为每个平台选择待渲染的音频缓冲区的大小,以及在当前可听缓冲区之前要渲染的缓冲区数量。

音频混成器线程模式

音频混成器会创建自己的线程,以执行实际的音频渲染。我们称之为 音频渲染线程 。此线程不同于 音频线程 ,它会执行DSP源生成和混合的所有相关工作。

音频线程 的工作是确定要播放的音效以及相关参数(处理声音提示、音效类、音效混合、衰减等)。对于音频混成器和旧有的平台特定音频引擎,音频线程基本相同。音频线程目前在处理UObject和垃圾回收方面较为复杂。由于音频线程有UObject,因此垃圾回收期间它会被隔离并停止。在运行时,这些UObject是只读的。但在编辑器中,由于这些UObject是可写入的,因此我们不使用音频线程。

基于回调的平台API中还有一个硬件线程,实际的平台硬件回调就是根据该线程执行的。此硬件拥有的线程回调几乎总是使队列中的已渲染缓冲区从音频渲染线程中脱离,并且很少做实际工作。

最后,音频引擎利用UE4任务图中的异步任务进行解码和生成过程音频(如合成)。

生成声源

音频混成器渲染自身的第一阶段是生成源。为了生成源,音频混成器接收从游戏和音频线程发出的参数,这些参数定义要播放的声源及其参数(如音量、音调和位置)。

这里用的词是 ,因为从该源生成的音频可能派生自压缩音频资源(如音效文件),通过程序生成(通过合成、解码的媒体、VOIP或麦克风捕捉),或其源派生自混合起来的其他源(例如 源总线 )。不同情况下,生成源数据的方法也各有不同。

编码的声源

如果是编码的声源(ogg-vorbis、opus、atrac9、xma2、adpcm等),则使用异步任务将音频解码到未压缩的32位浮点缓冲区中。然后,此32位浮点缓冲区执行采样率转换(SRC),从源的采样率转换为音频混成器的采样率。此SRC流程考虑了所有也可能已应用到声源的 音调比例 ,并仅执行SRC一次。

例如,若由于音效设计人员想要调高声源,因而在32kHz和1.2音调比例下对声源进行编码,或者若音频混成器正在以48kHz的频率渲染音频,则SRC将使用以下采样率:

SampleRateRatio = (48 kHz/32 kHz) * 1.2

SampleRateRatio = 1.8

这意味着在音频解码后,它会将声源调高1.8。

过程(生成的)声源

若是过程声源,则音频通过抽象接口生成,该接口回调客户端代码,生成下一个32位浮点缓冲区。客户端代码可将任何音频馈送到此回调中,理论上该音频可能来自任意源。在UE4中,我们用它执行实时合成,渲染媒体源中的音频(例如播放3D视频中的音频,包括衰减、遮挡或带有实时效果),或播放VOIP中的音频。

这也是第三方插件扩展音频引擎的多种方式之一。过程声源可在插件中定义,源音频可从任意其他源馈送至音频混成器,包括完全独立的音效引擎。

混合源

音频混成器还支持混合声源,以创建其他源。这些混合源称为 源总线 。源总线类似于任何其他源,支持其他源具有的大部分功能,例如空间化、距离衰减、音量混合和源效应处理。此功能有多种有用的应用:声源到新空间位置的动态路由(如无线电广播)、空间化效果处理(如基于位置的混响处理),以及延迟型空间效应(如场景中特定对象回弹音频)。

声源DSP效果处理

声源生成音频后,输出会通过 音频DSP效果 链馈送。还有一些所有声源都自动可用的内置效果。这些DSP效果是高通滤波器和低通滤波器,并用于各种高级功能。

通过 声衰减设置 ,音效设计人员可映射高通和低通功能的滤波器截止频率,以应用到单独的声源,作为与监听者的距离的函数。

另一个使用此逐源滤波器的功能是内置的 遮挡系统 。若已启用遮挡,当声音被遮挡几何体阻拦(通过异步光线追踪确定)时,它将自动应用音效设计人员定义的低通滤波器。最终,音效混合和音效类可将逐源低通滤波应用于音效。

除了内置的自动滤波效果,还可通过所谓的 源效应链 自动进行滤波。这是一种定义一系列逐源DSP效果的资源,这些效果是通过源效应插件API创建的,包括合唱效果、飘忽效果、延迟、高级滤波、环形调制、比特粉碎等等。

子混音图

生成源之后,音频混成器处理 子混音图 。子混音图的输出是音频硬件上听到的音频。

发送到子混音

主子混音 在音频引擎初始化时创建于音频引擎中。默认情况下,若无其他子混音被指定为基础子混音,则所有声源都自动注册到此子混音中,作为 基础子混音

源的基础子混音是最大音量的源输出混合而成的子混音(衰减后,空间化后)。也可指定任意数量的 发送 子混音,将源混合起来,再通过辅助DSP效果发送。这些发送子混音类似于DSP效果的辅助通道,如数字音频工作站或混音控制台中的混响。

如前文所述,若声源未指定任何子混音路由,则使用默认路由。但有两大方法可控制声源将其音频发送至子混音的位置。第一种方法是指定基础子混音。此子混音混合最大音量的音效。若留空,则将音频路由至EQ子混音或主子混音,具体取决于旧有功能。

主子混音

除了主子混音,还会创建两个 主音效子混音 并作为子项添加到此主子混音。即 主混响子混音 主均衡器(EQ)子混音 。创建这些主子混音主要用于兼容UE4中的旧有功能,以及帮助将现有项目交换至音频混成器。但它们是支持与混响和EQ交互的音效类、音效混合、音量和声衰减中各种高级功能的底层机制。

生成输出

主子混音是子混音图的根节点。通过检索从此主子混音生成的音频,从而生成最终输出。

各个子混音对象的输出是通过以下方式生成的:首先生成子混音的子混音子项的输出,然后将此输出与已注册(或发送)到它的任何源混合在一起。已注册声源的发送量是子混音中混合在一起的声源的增益/衰减。

此混合缓冲区混合到硬件的输出通道配置中。例如,对于立体声输出,这将是双通道音频缓冲区。对于7.1的音频,则是八通道音频缓冲区。

然后,此混合交织音频通过子混音的DSP效果链馈送,最终生成输出。

其他子混音功能:分析、录制和监听

子混音是执行音频分析的理想对象。目前有一种用于注册蓝图委托的机制,可逐通道从子混音中检索振幅包络值。对于很多要与音频进行交互的可视化系统或游戏系统来说,此功能很有用。还有一种实时FFT委托,可用于从蓝图中的子混音中检索光谱数据。

子混音还有一个功能,可以将输出记录到USoundWave对象或将原始PCM(.wav)文件记录到磁盘。

最后,还有一种可由其他代码系统注册的C++委托,用于从任何子混音中动态地检索混合音频。此功能可用于许多有用的功能,如网络广播(用于游戏的服务器流送)或第三方插件扩展。

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消