Unity中Wwise音频可视化及游戏内录屏方案的思路探索

音频编程 / 游戏音频

一、前言:

希望本篇分享能抛砖引玉,激发大家更多的开发灵感。

在游戏的实际开发过程中,你是否经历过以下两个场景:

  1. 场景一:策划小姐姐跑过来说,我们需要美术特效跟随音频的变化去变化

  2. 场景二:策划小姐姐又跑过来说,我们想做个游戏内录屏的功能,玩家点击录屏按钮会录一个带声音的视频

仔细分析,我们不难发现,场景一中策划小姐姐的需求本质,其实就是我们经常讨论的音频的可视化实现。那么,场景一中如何实现Wwise音频可视化和场景二中的如何实现录制Wwise里输出的音频,这两个问题的本质又是什么?

没错,是如何获取Wwise底层的音频采样数据?

那么我们今天讨论的主题就变成了:如何获取Wwise底层的音频采样数据并发送到Unity中进行接收?

二、如何获取Wwise底层的音频采样数据并发送到Unity中接收?

我们可以把这个问题拆分为2个问题:

  1. 如何获取Wwise的底层音频采样数据?

  2. 获取到数据之后又如何发送到Unity中?

在本文探索的方案思路中,上述拆分之后的2个问题的回答如下:

  1. 如何获取Wwise的底层音频采样数据?

答:编写并构建你的Wwise Effect Plugins

  1. 获取到数据之后又如何发送到Unity中?

答:编写并构建数据中转插件,且称他为中转器。Unity中通过DllImport的形式,将中转器动态库库导入……

那么,根据上述2个问题的回答,下文将从Wwise Effect Plugins数据中转器Wwise、中转器和Unity之间的互联三个方面逐步探索。

1、Wwise Effect Plugins

我们可以把Wwise理解为是一个密封的黑盒子,我们所需要的采样数据就存在这个黑盒子里的某个地方。Wwise官方并没有开放相关的Api,因此我们从外面是无法把“手”伸进黑盒子里直接拿到数据的。所以,我们只能另辟蹊径,而编写插件就是那条蹊径。

由于我们编写的插件仅仅用来捕获Wwise底层数据用,因此插件的GUI层面不需要加入什么东西,所以当我们构建好开发Wwise效果器插件的vs工程之后,直接进入声音引擎逻辑编写部分。当然,如果你觉得必须要放点什么在插件面板上的话,那么,你可以……

比如:image001

扯远了,回到正题。

我们所编写的Effect Plugins就像一个“间谍”潜伏在Wwise这个黑盒生态系统中,时刻为我们拿到需要的情报(数据)。拿到之后势必要有一辆“运输车”去装载数据,那么,我们先构建这辆“运输车”。

直接进入声音引擎编写部分,在头文件声明:

image003

在插件的构造函数中将其初始化为nullptr

进入插件的Init()函数中,为其申请一个大小为2048的浮点型数组的内存

image005

为此wwise提供了AK_PLUGIN_ALLOC宏:

image007

为什么大小是2048呢?

这个取值不是死的,取决于你的设置,因为我的音频输出设置为Stereo,采样点数为1024,所以我这里固定了大小为2048.

在插件的Term()函数中释放这部分内存:

image009

Wwise提供了AK_PLUGIN_FREE宏:

image011

这样便完成了“运输车”的构建。

那么,我们现在开始往车上装填数据。

进入插件的Execute(AkAudioBuffer* io_pBuffer)函数中:

image013

在上述代码中,audioDataForSend数组中存入的是来自wwise所有通道的音频数据,并且整个存储的过程是不同通道交错访问存储的。也就是说,其中相邻的数据分别来自于不同的通道,举个例子,比如第10个数据来自于左通道,那么第9个和第11个数据来自于右通道。这样在两个for循环的不断刷新执行下,当outPosition值等于2047的时候,便完成了当前音频帧的所有音频数据的“装车“

这里,我以我拙劣的画技画了一幅数据“装车”的示意图:

image015

数据“装车”之后,面临的问题是如何将数据运输到Unity中?实际上,UnityWwise这两个密闭的系统之间是没有“路”可以供“运输车”行驶的。那么,我们势必要动手开辟一条连接UnityWwise的通路,就像连接候机大厅与飞机之间的登机通道,或者连接两座悬崖绝壁的索道一样。

数据中转器便是连接UnityWwise的通路上的一个重要枢纽。

2、数据中转器

中转器是连接UnityWwise的一个重要枢纽,它以动态库的形式存在。关于动态库构建方面的知识本篇分享就不延展来说了,因为这里又涉及很多方面的内容。

中转器的职能简单来说就是:接收Wwise传来的数据,并扔到Unity过来接收的车上

实际上,在本文提供的思路中,构建中转器动态库的C++代码中只需要两个相同参数类型的导出函数。

比如:

image017

上述代码中,我们可以看到有2个相同参数类型的函数。虽然参数相同,但是他们的实际职责却是各不相同的。一个用于Wwise与中转器的连接,另一个则用于Unity与中转器的连接。详情看下文

3、Wwise、中转器、Unity三者之间的互联

Wwise&中转器

Wwise与中转器的连接过程涉及动态库的读取加载、函数指针的获取等等。

Wwise插件编写声音引擎部分,声明一个函数类型指针,其类型与中转器中的函数一样:

image019

Execute(AkAudioBuffer* io_pBuffer) 函数中,在数据装车完成之后,加入以下代码:

image021

上述代码中, 我们通过LoadLibrary() Windows 系统APILinux系统下是dlopen())获取动态库句柄,通过GetProcAddress() 获取函数指针。这里我们获取中转器中GetSamplesFromWwise函数指针。通过函数指针完成函数的执行。

至此完成Wwise与中转器的连接,实现数据Wwise到中转器的转移。

Unity&中转器

在完成Wwise与中转器的连接之后,我们考虑连接中转器与Unity

Unity与中转器的连接涉及Unity动态库导入、外部库函数的定义以及非托管层与托管层之间数据的转换传输等等。

C#中导入库并声明外部库函数:

image023

非托管层与托管层之间的数据转换运算,C#提供了Marshal 供我们使用。我们通过Marshal 中的接口实现内存的申请,数据的copy等操作。调用Dllimport导入的外部库函数,实现c#层面对于音频数据的获取。

比如:

分配一个2048大小的float类型数组内存:

image025

将一个数组拷贝到另一个数组:

image027

释放:

image029

实际上,我们为了方便在Unity项目中C#层面更快捷地接收Wwise的数据,可以将我们导入的库函数和Marshal 中的接口一起封装成一个函数,方便我们使用,比如:

image031

至此、就完成了Unity与中转器的连接。与此同时,一条Wwise通往Unity的数据“运输之路”修建而成,Wwise的音频数据便可传入Unity中接收、使用。

拿到了Wwise的音频数据之后,至于波谱、频谱、录屏等等功能需求的满足便易如反掌了。

举个例子,我们可以修改项目使用的录屏插件里的音频模块的逻辑,达到将来自Wwise的音频数据写入录制的视频中的目的。

你要捕获什么音频数据就把效果器插件挂到对应的总线上。比如,想获取仅仅来自音乐的音频数据,那就把插件挂到音乐系统输出的音乐总线上。那么,你录到的视频里面就只有音乐没有音效了。

三、总结:

以上所说的整套Unity中获取Wwise音频数据的流程,这里我又展示了我拙劣的画技,如下:

image033

效果视频

以下视频,我将拿到的Wwise音频数据,在Unity中绘制了一下:

(国内观赏视频通道

最后

考虑到性能、兼容性,跨平台开发等因素的影响,实际的开发过程还是比较复杂,比较麻烦的。

如本篇开头所说,希望本篇分享能起到抛砖引玉的作用,让大家在实际的游戏开发过程中能够产生更多好玩的想法或灵感。

如果你有更好的方案或想法,欢迎交流。

 

张成功

技术音频

盛趣游戏

张成功

技术音频

盛趣游戏

技术音频、独游开发爱好者,目前任职于盛趣游戏。一个喜欢喝粥的男人,在研究点技术的同时,也会搞些音乐上的事情讨好自己。希望游戏听起来更好。

评论

留下回复

您的电子邮件地址将不会被公布。

更多文章

为你的游戏声景调音:声音设计背后的音乐理论

在 2017 年蒙特利尔国际游戏峰会 (MIGS17) 期间,Ubisoft 音频总监文森特·加格农 (Vincent Gagnon) 发表了题为 Music Theory for Sound...

16.10.2018 - 作者:Audiokinetic (音频动能)

为 Wwise 2021.1 构建插件 | 第 1 部分:背景和目标

大家可能不知道,Wwise 生态系统其实具有很强的可扩展性。有时,各公司要为其项目构建定制的插件,供应商会将自研插件迁移到 Wwise。对此,我们必然要提供相应的支持。新的 Wwise...

27.9.2021 - 作者:米歇尔•多奈斯 (Michel Donais)

利用 Wwise 设计基于循环的汽车发动机声音 | 第 1 部分

在本系列博文中,我们将介绍如何利用 Wwise 设计基于循环的汽车发动机声音(文中配有相关音频示例,及有关汽车的基础知识)。 ...

26.1.2022 - 作者:阿托•科伊维斯托 (Arto Koivisto)

《刺客信条:英灵殿》— 沙盒音乐系统

9.6.2022 - 作者:亚历山大•波里耶(Alexandre Poirier)

WAQL 2.0

自 Wwise Authoring Query Language (WAQL) 的第一个版本发布以来已经有几年了。在此之后,几乎没什么改动。最大的改动就是把 WAQL 集成到了 Wwise...

10.8.2023 - 作者:伯纳德 罗德里格 (Bernard Rodrigue)

利用 Wwise 在《Saints Row (2022)》中再现现实世界中的电台|实例分享

最初在《Saints Row...

25.11.2024 - 作者:Brendon Ellis

更多文章

为你的游戏声景调音:声音设计背后的音乐理论

在 2017 年蒙特利尔国际游戏峰会 (MIGS17) 期间,Ubisoft 音频总监文森特·加格农 (Vincent Gagnon) 发表了题为 Music Theory for Sound...

为 Wwise 2021.1 构建插件 | 第 1 部分:背景和目标

大家可能不知道,Wwise 生态系统其实具有很强的可扩展性。有时,各公司要为其项目构建定制的插件,供应商会将自研插件迁移到 Wwise。对此,我们必然要提供相应的支持。新的 Wwise...

利用 Wwise 设计基于循环的汽车发动机声音 | 第 1 部分

在本系列博文中,我们将介绍如何利用 Wwise 设计基于循环的汽车发动机声音(文中配有相关音频示例,及有关汽车的基础知识)。 ...