目录

Wwise SDK 2018.1.11
集成 External Source

External Source 是在 Wwise 里您可以放到声音对象中的一种特殊类型的源(Source)。它表明在运行时将采用真实声音数据。这对于管理大量对白非常有用。如果没有它,则需要为每行对白准备一个声音对象和一个事件,并需要将声音对象和事件打包到 SoundBank 中,并进行适当的分包管理。如果已经在使用别的系统(例如由人工智能驱动的语音生成器)管理对白,则 External Source 也同样非常有用。

在 Wwise 中创建 External Source 的方式与创建其他源插件一样,都是通过Add Source按钮,如果需要,可让它成为复杂结构的一部分。在游戏端,使用 External Source 播放事件与播放其他声音一样都是通过 AK::SoundEngine::PostEventAK::SoundEngine::DynamicSequence::Playlist::Enqueue 来实现的。当发送事件时,需要提供用来替换 External Source 的波形文件。具体播放哪个文件,完全由程序员决定。这同时意味着源文件的文件管理是在 Wwise 声音引擎外部来完成的。虽然这需要更多的工作量,但同时也提高了灵活性。

External Source 的转码

声音引擎使用的波形数据采用专用格式;您需要转码您的输入文件,以便在运行时将它们传输给声音引擎。这通过 Wwise 中的 External Source 文件列表完成。这是一个非常简单的 XML 文件,其中包含您需要转码的所有文件和您要使用的转码设置。要指定 wsources 文件,请访问 External Sources 选项卡中的 Project Settings。以下是此文件的示例:

<?xml version="1.0" encoding="UTF-8"?>
<ExternalSourcesList SchemaVersion="1" Root="d:\TestProject\ExternalSources">
<Source Path="kaaboom.wav" Conversion="VeryCompressed" />
<Source Path="SomeOtherFolderInTheProject\working.wav" Conversion="PCM"/>
<Source Path="d:\FolderOutsideTheProject\out.wav" Conversion="PCM" Destination="out.wav"/>
<Source Path="..\RelativeOutsideTheProject\relative.wav" Conversion="PCM" Destination="relative.wav"/>
<Source Path="MyHdrSound.wav" Conversion="PCM" AnalysisTypes="6"/>
</ExternalSourcesList>

Root 属性指定源条目的根路径。如果省略此属性,则工程目录将被视为根路径。Root 路径可以是完整路径,也可以是相对于工程目录的相对路径。

Source 条目指定要转码的一个文件:

  • Path 始终代表相对于 Root 的路径。
  • Conversion 属性是用于转码文件的 Conversion Setting ShareSet(转码设置共享集)的名称。如果未指定,它则将使用工程的 Default Conversion Setting(默认转码设置)。
  • Destination 属性是可选的,可让您指定不同的目标文件名和路径。此路径是 Project Settings 或命令行中指定的输出路径的相对路径。您也可以使用此属性对文件重命名。注意,您不能只使用文件路径:您还需要指定文件名。另外,无论 Destination 属性的扩展名是什么,转码文件的扩展名始终是“.wem”。如果未指定 Destination 属性,则输出路径中总是会复制 Root 目录下的文件夹层级结构。如果您使用 Root 目录外的文件,则必须指定 Destination 属性。
  • AnalysisTypes(分析类型)用于确定转码文件的文件头中应包含的分析元数据类型。声音引擎可使用的分析类型目前有两种:Loudness(响度)和 HDR。 – 响度用于响度归一化,如果某目标声音结构勾选了“Enable Loudness Normalization”复选框,则您应该为其 External Source 添加 Loudness 分析类型。要包含 Loudness 分析类型,则要设置 AnalysisTypes 为 2。 – HDR 主要由声音的包络构成。如果您打算为勾选了“Enable Envelope”复选框的目标结构使用HDR系统,则应在其内源中包含 HDR 分析类型。要包含 HDR 分析类型,则要设置 AnalysisTypes 为 4。 – 设置 AnalysisTypes 为 6(即 2 + 4)会同时包含这两种类型。

External Source 的转码是在生成 SoundBank 时与所有其他文件转码一起自动完成的。注意,已经转好码的文件不会再白白重新转码。

Caution: 为了避免重新转码,Wwise 会将一些数据保存到输出目录下的 Wwise.dat 文件中。此文件对于游戏来说不是必要的,因此不应包含在最终发布的文件中。如果此文件已被删除,在所有波形文件将重新转码。

输入目录的目录结构将相对于根目录复制到输出目录下。在上述示例中,输出目录包含“ExternalSources”文件夹和“Lower Tests\Originals\SFX”文件夹。注意,路径中包含的“..”将被去除,而从该路径中第一个真正的文件夹开始。

命令行转码

通过命令行工具,还可只转码工程的 External Source。例如,此命令将为 Xbox One 转码 External Source,不会产生 SoundBank。

"%WWISEROOT%\Authoring\x64\Release\bin\WwiseCLI.exe" "C:\Project name.wproj" -ConvertExternalSources XBoxOne

有关命令行工具(WwiseCLI)的详情,请参阅 使用命令行

流播放与内存播放

要为声音引擎提供音频数据,您可以在 AkExternalSourceInfo 结构中指定文件名,也可指定数据指针。这样会完全覆盖 Wwise 工程中声音对象上的 Streaming 复选框。当使用数据指针时,您将负责内存管理,并确保在整个播放期间数据一直保持在内存中。

当指定文件名时,文件将被打开,并像正常的流播放文件一样从磁盘中流式播放。文件在磁盘中的位置必须在 Low-Level I/O(底层 I/O) 子系统中通过实现 File Location Resolver(文件位置解析器)来解析。请参阅 Low-Level I/O 了解有关 Low-Level I/O 子系统的详情。

默认的文件位置解析器服务位于 CAkFileLocationBase 中,并作为 SDK 中的示例提供给用户(请参阅 默认底层 I/O 实现 )。该实现不支持子文件夹;它假定各个 External Source 流播放文件与“标准”的流播放文件放在同一位置。

Wwise Stream Manager 将若干标识传递给 AK::StreamMgr::IAkFileLocationResolver::Open(),以帮助您正确解析文件位置(AkFileSystemFlags)。在此抽象层次上,通过使用“公司 ID”(AkFileSystemFlags::uCompanyID),您可以将 External Source 与标准流播放文件区分开来。对于 SoundBank 和标准流播放文件,Wwise 传递的是 AKCOMPANYID_AUDIOKINETIC,而对于 External Source,传递的则是 AKCOMPANYID_AUDIOKINETIC_EXTERNAL。因此您可以使用此值来搜索磁盘别的位置上的 External Source。

Note: 对于 External Source,AkFileSystemFlags::bIsLanguageSpecific 要始终设为 false,即使 External Source 包含在“Voice”(语音)声音结构中也是如此。事实上,我们建议您在独立于语言的 Sound SFX 对象中使用 External Source 而不要在 Sound Voice 中使用。当在 AkExternalSourceInfo 中指定文件名或 ID 时,必须从一开始就处理本地化。

示例:通过 External Source 机制播放单个声音

工程必须包括:

  • 名为 MySound 的声音,并且配备一个名字也为“MyExternal”的 External Source(通过“Add Source”按钮添加)
  • 播放事件“Play_MySound”
  • 包含了该事件的 SoundBank
  • 工程设置中的 External Source 列表(见上例)
  • External Source 列表必须定义源“One.wav”和“Two.wav”(分别在“One.wem”和“Two.wem”中隐式转码)。
source.iExternalSrcCookie = AK::SoundEngine::GetIDFromString("MyExternal"); // cookie 是 External Source 对象名称的哈希索引。
source.szFile = AKTEXT("One.wem"); //我们将播放的文件。
source.idCodec = AKCODECID_PCM; //此文件位于 PCM 中。
AK::SoundEngine::PostEvent( "Play_MySound", 2, 0, NULL, 0, 1, &source );
source.szFile = AKTEXT("Two.wem"); //让我们播放含有相同事件/源的另一个文件
AK::SoundEngine::PostEvent( "Play_MySound", 2, 0, NULL, 0, 1, &source );
Note: 外部文件的扩展名必须是“.wem”。在 External Sources File List 文件中,您可以重命名目标文件,但不可更改其扩展名。一旦转码,文件的扩展名始终为“.wem”。如果您将转码好的文件打包成 File Package(文件包),则还需要在代码中用其扩展名“.wem”引用它:File Packager(文件打包器)通过哈希算法来为完整名称(包括扩展名)来生成查询 ID。

示例:使用多个 External Source 播放事件

您可以通过一个单一事件替换许多波形文件。例如,您可以设置装有 3 个 External Source 的序列容器。如果事件可触发播放多个 External Source,则这些 External Source 在整个工程中不得重名(因此各自能有独一无二的 cookie),以便在填充 AkExternalSourceInfo 结构时能够区分它们。

工程必须包括:

  • 名为 MyExternalSequence 的序列容器,装有 3 个声音,每个声音有一个 External Source(通过“Add Source”按钮添加)
  • 源名称应为 1、2 和 3,以便我们能够分别替换它们。
  • 播放事件“Play_MyExternalSequence”
  • 包含了该事件的 SoundBank
  • 工程设置中的 External Source 列表(见上例)
  • External Source 列表必须定义源“One.wav”、“Four.wav”和“Five.wav”(分别在“One.wem”、“Four.wem”和“Five.wem”中隐式转码)。
sources[0].iExternalSrcCookie = AK::SoundEngine::GetIDFromString("Extern_1st_number");
sources[0].szFile = AKTEXT("Five.wem");
sources[0].idCodec = AKCODECID_PCM;
sources[1].iExternalSrcCookie = AK::SoundEngine::GetIDFromString("Extern_2nd_number");
sources[1].szFile = AKTEXT("One.wem");
sources[1].idCodec = AKCODECID_PCM;
sources[2].iExternalSrcCookie = AK::SoundEngine::GetIDFromString("Extern_3rd_number");
sources[2].szFile = AKTEXT("Four.wem");
sources[2].idCodec = AKCODECID_VORBIS; //如需要,各个源的编解码器可以不同
AK::SoundEngine::PostEvent( "Play_MyExternalSequence", 2, 0, NULL, 0, 3, sources );