目录

Wwise SDK 2018.1.11
流播放/流管理器

简介

有限的带宽往往会使得存储设备的访问速度成为游戏的瓶颈。因此,为了保持良好的数据传输请求顺序,游戏通常会集中访问 I/O。排序的依据是相对优先级、相对于传输大小的开销要求、吞吐量和延迟。音频一般需要大量的 I/O 资源:音乐和较长的声音在播放时通常从磁盘传输。

Audiokinetic 的 I/O 流播放解决方案

Audiokinetic 声音引擎的 I/O 流播放解决方案由自主的、可重写的流管理模块构成。下列流程图展示了该模块及其在声音引擎/游戏架构中的位置:

Streaming_WithCustomLowLevelIO.gif

流管理模块的公共接口在 IAkStreamMgr.h 中定义,供声音引擎和游戏共同使用。前者使用此接口来加载 SoundBank 和流播放音频文件,而后者可用它来加载图形、纹理、游戏关、保存的游戏等。

该公共接口是进行数据传输所用存储(I/O)设备的高层抽象,它独立于平台,将平台底层操作系统或硬件中,文件或其他对象的句柄封装成所谓的“流”。在本文档中,实现流对象和流创建的模块被称为 High-Level Stream Manager,简写为 Stream Manager。

如果需要,您可以完全重写 Stream Manager,但 Wwise SDK 自带了一个默认实现。此默认实现定义了另一个可以将 I/O 相关代码挂钩的层级,称为 Low-Level I/O,使用起来会更便捷。它是将 Wwise I/O 集成到游戏中的首选方式。

Default Streaming Manager Information

Note: 在本章中,您将遇到与此类似的方框,其中提供了有关 Audiokinetic Stream Manager 的更多详情。

默认 Stream Manager 中特定的流播放相关函数和结构(例如 AK::StreamMgr::Create())定义于 SDK include 目录下的 AkStreamMgrModule.h 中。

集成 Wwise I/O

快速集成

为了在第一次集成 Wwise 时快速入门,请使用 Wwise SDK 随附的默认 Stream Manager 和 Low-Level I/O 示例:

1)链接 AkStreamMgr.lib。

2)在游戏工程中包含默认的 File Location Resolver( File Location Resolver )和 Blocking I/O Hook(阻塞 I/O 挂钩):

  • SDK/Samples/SoundEngine/{Platform name}/AkDefaultIOHookBlocking.h and .cpp
  • SDK/Samples/SoundEngine/{Platform name}/AkFileHelpers.h
  • All the files in SDK/Samples/SoundEngine/Common/

3)创建 Stream Manager 后,实例化和初始化 Low-Level I/O 挂钩设备 CAkDefaultIOHookBlocking。注意,您可以使用 CAkFilePackageLowLevelIOBlocking,它实现了支持 File Package 扩展名的 I/O 挂钩(请见下一节)。当您需要时,它将准备就绪。请参阅 初始化 Streaming Manager 了解有关如何将其初始化的示例。

4)需要将 Wwise 创作工具生成文件所在的目录告知默认 File Location Resolver (在 CAkFileLocationBase 中实现)。在您的代码中,使用 CAkDefaultIOHookBlocking::SetBasePath()(或 CAkDefaultIOHookBlocking::AddBasePath())设置来部署音频素材的基本路径。如果您有本地化语音资源,请使用 AK::StreamMgr::SetCurrentLanguage() 为默认 Stream Manager 模块设置当前语言。默认 File Location Resolver 将语言名称与基本路径组合起来,用于查找本地化资源。

Warning: 请勿在传输给 AK::StreamMgr::SetCurrentLanguage() 的语言名称后面附加目录分隔符(斜线或反斜线)。

声音引擎现在可以加载 SoundBank 并从 SetBasePath()(或AddBasePath())中指定的目录中播放流文件了。 注意,为了自动将流文件复制到 Wwise 工具的 SoundBank 输出目录中,应使用“CopyStreamedFiles”可执行文件作为post-soundbank-generation step( SoundBank 生成后续步骤)。请参阅 Wwise 帮助文档的 SoundBank Settings( SoundBank 设置)部分来了解更多详情。

文件包

如果您已经将 CAkFilePackageLowLevelIOBlocking 设备实例化,只需几步就可以使用 File Package 了。 文件包(*.PCK)是通过将 Wwise 工程中的所有 SoundBank 和流音频文件组合形成单一文件。您还可以将 SoundBank 和流文件分配给不同的文件包。请参阅 File Packager 实用程序文档了解更多详情。

1)在生成 SoundBank 后,将“FilePackager”可执行文件作为生成 SoundBank 的后续步骤,可以让该 Wwise 工具使用 SoundBank 和流文件自动生成文件包(请参见 Wwise 帮助的 SoundBank 设置一节)。

2)在您的代码中,使用 CAkFilePackageLowLevelIOBlocking::LoadFilePackage() 来显式加载文件包。LoadFilePackage() 将从 SetBasePath()(或 AddBasePath())中指定的路径打开文件包。在音频素材的部署目录中,您需要添加文件包,但不包括它们所包含的 SoundBank 和流文件。加载文件包时,将解析其文件头,并在 CAkFilePackageLowLevelIOBlocking 内创建查找表。当声音引擎试图打开文件时,调用了 AK::SoundEngine::LoadBank() 或触发了播放流文件相关的事件后,CAkFilePackageLowLevelIOBlocking 将在所有已加载文件包的查找表中搜索该文件。如果未找到,则在基本路径中查找该文件。

使用您自己的 I/O 管理器进行 I/O 读取操作

CAkDefaultIOHookBlocking 使用平台文件系统 API 读取文件。如果游戏引擎已包含 I/O 管理器,可能需要将 Wwise Stream Manager 发布的 I/O 读取请求指定至您自己的 I/O 管理器。编辑 CAkDefaultIOHookBlocking::Read() 来调用您自己的 I/O 管理器而非平台文件系统。如有必要,还可以编辑 CAkDefaultIOHookBlocking::Open()

深入探索:使用 Low-Level I/O

SDK 中的默认 Stream Manager 位于 Low-Level I/O 子模块上。 上文所述的类均作为 Low-Level I/O 的示例在 Wwise SDK 中提供。 它们的相关文件位于:默认底层 I/O 实现

将 Wwise I/O 集成到游戏引擎中的首选方式,是将 Low-Level I/O 层作为 Wwise I/O 与您的 I/O 管理技术之间的转接口。游戏中的典型 Low-Level I/O 示例种类繁多,从非常简单的示例到极端复杂和高度自定义的示例都有,您可以使用这些示例作为起点。

Low-Level I/O 模块有两个用途:

  • 解析磁盘中的文件位置:由 Wwise 生成的文件可以放置在游戏磁盘的任何位置,但必须编写代码来确保 SoundBank 和流文件的名称及 ID 与平台文件系统所用的文件描述符之间正确映射。
  • 所有 Low-Level I/O 操作的抽象:由 Stream Manager 调度的所有 I/O 传输请求(读/写)均在此完成。

Wwise I/O 性能

Stream Manager 的初始化设置将影响它与 Low-Level I/O 系统间的互动方式以及整个 I/O 性能。 Audiokinetic Stream Manager 初始化设置 一章中对此进行了全面描述。I/O 技巧、故障排除和优化 章节讲述了如何对其进行微调。

高层 Stream Manager

Stream Manager 的接口在 IAkStreamMgr.h 中定义,Wwise 声音引擎使用 Stream Manager 来读取 SoundBank 和流音频文件。如果还没有 I/O 管理器,也可以将其用于所有游戏 I/O。同样,如果您编写自定义源插件,也可以访问 Stream Manager。

高级 Stream Manager API 说明 一节中详细地解释了它的 API。如果您不将其直接作为客户端,而仅通过实现 Low-Level I/O 挂钩将 Wwise I/O 集成到游戏中,则可以跳过本章。

以下是一些基本概念。Stream Manager 管理两种数据类型的抽象流:标准流和自动流。

Stream Manager 是线程安全的,但只有一个线程可以占用指定流。

主要接口 AK::IAkStreamMgr 可以随时通过调用 AK::IAkStreamMgr::Get() 来访问。随后您将可以创建和使用流对象。

更多信息

以下章节提供有关流播放的更多详情: