Wwise 版本
arrow_right 目录
Wwise SDK 2021.1.5
Wwise 插件 XML 描述文件

Wwise 的开放式架构支持各种不同的插件:

  • 音频插件。其中包括:
    • 源插件,用于生成声音
    • 效果器插件,用于变换声音
    • Sink 插件,用于向媒介输出声音
  • 版本控制插件,允许在 Wwise 内使用版本控制软件

音频插件以 XML 文件的形式描述其模型。藉此,无需重新编译代码便可快速更改插件的各项设置,包括默认属性值。倘若插件没有提供自定义 GUI,还可使用此模型中描述的属性,在 Wwise 中以属性表的形式提供默认图形界面。

XML 文件概述

XML 描述文件包含有关 Wwise 插件的多方面信息,包括:

  • 插件名称
  • 公司 ID 和插件 ID。请参阅 Wwise 插件 ID 了解详情。
  • 各平台所支持的功能
  • 属性定义,包括:
    • 属性名称(在代码中和持久化文件中标识属性的字符串)
    • 属性类型
    • RTPC 支持
    • 默认值
    • 声音引擎属性 ID(将此属性绑定到声音引擎插件的代码中)
    • 值域限制或枚举限制
    • 对其他属性的依赖性
    • 用户界面描述元素
  • 内部对象类型定义,包括:
    • 内部对象类型名称(标识内部对象类型的字符串)
    • 内部对象属性

在使用 wp.py 开发工具时,会提供默认的 XML 文件并预先填入创建时提供的信息。有关更多详细信息,请参阅 创建新的插件 章节。

备注: Wwise 插件动态库可包含多个插件(参见 设计工具插件库格式 章节),每个插件都必须在单独的关联 XML 文件中加以描述。

XML 文件命名

每个 Wwise 插件动态库的 XML 描述文件都要采用与动态库相同的名称,只不过 XML 文件扩展名不同且不带 lib 前缀。

比如,若将动态库命名为 MyPlugin.dlllibMyPlugin.dylib,则须将插件描述文件命名为 MyPlugin.xml

示例:XML 描述文件

以下是一个简单插件 XML 描述文件的示例。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2020 Audiokinetic Inc. -->
<PluginModule>
<EffectPlugin Name="Wwise Parametric EQ" CompanyID="0" PluginID="105">
<PluginInfo>
<PlatformSupport>
<Platform Name="Windows">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="Mac">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="iOS">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="XboxOne">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="PS4">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
</PlatformSupport>
</PluginInfo>
<Properties>
<Property Name="OnOffBand1" Type="bool" SupportRTPCType="Exclusive" ForceRTPCCurveSegmentShape="Constant" DisplayName="Band 1 Enable">
<DefaultValue>true</DefaultValue>
<AudioEnginePropertyID>4</AudioEnginePropertyID>
</Property>
<Property Name="FilterTypeBand1" Type="int32" SupportRTPCType="Exclusive" ForceRTPCCurveSegmentShape="Constant" DisplayName="Band 1 Filter Type">
<DefaultValue>5</DefaultValue>
<AudioEnginePropertyID>10</AudioEnginePropertyID>
<Restrictions>
<ValueRestriction>
<Enumeration Type="int32">
<Value DisplayName="Low Pass">0</Value>
<Value DisplayName="High Pass">1</Value>
<Value DisplayName="Band Pass">2</Value>
<Value DisplayName="Notch">3</Value>
<Value DisplayName="Low Shelf">4</Value>
<Value DisplayName="High Shelf">5</Value>
<Value DisplayName="Peaking">6</Value>
</Enumeration>
</ValueRestriction>
</Restrictions>
<Dependencies>
<PropertyDependency Name="OnOffBand1" Action="Enable">
<Condition>
<Enumeration Type="bool">
<Value>1</Value>
</Enumeration>
</Condition>
</PropertyDependency>
</Dependencies>
</Property>
<Property Name="GainBand1" Type="Real32" SupportRTPCType="Exclusive" DataMeaning="Decibels" DisplayName="Band 1 Gain">
<UserInterface Step="0.5" Fine="0.1" Decimals="1" />
<DefaultValue>0</DefaultValue>
<AudioEnginePropertyID>1</AudioEnginePropertyID>
<Restrictions>
<ValueRestriction>
<Range Type="Real32">
<Min>-24</Min>
<Max>24</Max>
</Range>
</ValueRestriction>
</Restrictions>
<Dependencies>
<PropertyDependency Name="OnOffBand1" Action="Enable">
<Condition>
<Enumeration Type="bool">
<Value>1</Value>
</Enumeration>
</Condition>
</PropertyDependency>
</Dependencies>
</Property>
</Properties>
</EffectPlugin>
</PluginModule>

XML 描述文件的各个部分

让我们详细地考察 XML 文件的各个部分。

XML 描述文件头

让我们考察此 XML 文件头的组成部分并详细地讨论。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (C) 2020 Audiokinetic Inc. -->

任何 XML 文件的第一行都是定义 XML 版本和编码方式。在本例中,XML 版本是 1.0,编码方式是 UTF-8 。任何 Wwise 插件描述文件的第一行应该总是与此完全一致。第二行是 XML 注释,在本例中是版权声明。您可以在 XML 文件的所需位置添加注释。

PluginModule元素

<PluginModule>
...
</PluginModule>

本文档中的主要 XML 元素命名为 PluginModule ,包含此文件中定义的各种插件的全部信息。

插件类型元素

在音频插件的类别中,有三个可能的插件类型元素:

  • SourcePlugin
  • EffectPlugin
  • SinkPlugin
<EffectPlugin Name="Wwise Parametric EQ" CompanyID="0" PluginID="105" SupportsIsSendModeEffect="false">
...
</EffectPlugin>

EffectPlugin 是定义单个效果器插件的主要元素,SourcePluginSinkPlugin 则分别为源插件和 Sink 插件的元素名称。

备注: 若在动态库中实现了多个插件,则 XML 文件将包含多个插件元素。 动态库并不限于某一类型的音频插件。

这些元素包含三个必需属性:

  • Name (必需):此字符串指定插件在 Wwise 中的实际显示名称。
  • CompanyID (必需):此字符串必须为介于 0-4095 之间的正整数(参见 wwiseplugin_xml_id_specification 章节)。
  • PluginID (必需):此字符串必须为介于 0-32767 之间的正整数。每个 PluginID 对于指定的 CompanyID 必须唯一。

可指定两个可选属性:

  • SupportsIsSendModeEffect (可选):(仅效果器插件)此布尔值通过在初始化期间查询 AK::IAkEffectPluginContext::IsSendModeEffect() 来指示插件是否支持发送模式。在 IsSendModeEffect() 返回 true 时,插件不应输出干声信号且应忽略干声电平属性。
  • EngineDllName (可选):此字符串值会覆盖游戏运行时所要加载的声音引擎动态库的名称(在默认情况下,名称与 XML 相同)。若指定了 EngineDllName ,请确保声音引擎静态库和动态库共用相同的名称。在商用游戏引擎(例如 Unity 和 Unreal 4)中,必须为您的插件提供 DLL/so 文件。这并不影响设计工具插件动态库的命名,其应与 XML 文件的名称严格对应。

Company ID 和 Plug-in ID

Wwise 使用数字 ID 将插件模型定义与插件实现关联。 每个插件的 XML 描述和插件库的插件描述符中都会提供这些 ID。

CompanyID 是一个与所在公司对应的 ID。其设有三个取值范围:

  • 0-63:预留给 Audiokinetic 使用,用户不可使用。
  • 64-255:无限制,供内部使用。 此范围之内的 Company ID 不可用于外部分发。
  • 256-4095:有限制,供商用插件使用。 Audiokinetic 将其分配给官方的第三方开发人员使用。如果您是官方的第三方开发人员之一,则可以使用 56-4095,而非 64-255 范围中的值。否则请勿使用这些值。

PluginID 是一个介于 0-32767 之间的唯一数字 ID,其与某一公司内部所用的插件对应。

比如,若您开发仅供内部使用的插件,则可在 64 ~ 255 之间任选一个 CompanyID,并在 0 ~ 32767 之间任选三个 PluginID。三个数字不需要连续。

CompanyID 和 PluginID 需要传给声音引擎插件声明宏 AK_IMPLEMENT_PLUGIN_FACTORY

注意: 重要注意事项:
  • 一定不要更改现有插件的 CompanyID 或 PluginID。否则使用该插件的工程将无法识别插件。CompanyID 和 PluginID 始终与各个插件实例保持一致,可用于在加载文件时重新创建所需插件的实例。
  • 如果同一个 CompanyID 具有两个或两个以上的相同 PluginID,Wwise 将在启动时显示错误消息。如果发生这种情况,则需更改新插件的 ID。
  • 若自研插件基于 Audiokinetic 提供的示例插件(参见 示例插件 章节),请不要忘记将 CompanyID 和 PluginID 改为适当的值。如果您有一个指定的官方 CompanyID,则使用它;如果没有,可以使用介于 64 与 255 之间的一个数。请确保该 CompanyID 的 PluginID 不重复。

有关 ID 的更多详细信息,请参阅 Wwise 插件 ID 章节。

PluginInfo 元素

<PlatformSupport>
<Platform Name="Windows">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="Mac">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="iOS">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="XboxOne">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
<Platform Name="PS4">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
</PlatformSupport>

PluginInfo/PlatformSupport 部分定义了插件支持的平台。它能包含一个或更多 Platform 要素,其中每个都指定了每个平台上插件支持的不同特性。可指定以下功能:

  • CanBeInsertOnBusses 确定效果器是否可用来控制和主导总线。通常这需要效果器支持环绕声音频配置。
  • CanBeInsertOnAuxBusses 确定效果器是否可用来控制和主导辅助总线。通常这需要效果器支持环绕声音频配置。注意,如果已经设置 CanBeInsertOnBusses,则效果器就已经可应用于辅助总线。
  • CanBeInsertOnAudioObjects 确定效果器是否可作为作用于音效的插入效果(必须支持单声道和立体声处理)。
  • CanBeRendered 确定效果器是否可用于离线渲染。
  • CanSendMonitorData 决定效果器是否可发送监控数据。有关详细信息,请参阅 AK::Wwise::Plugin::Notifications::Monitor::NotifyMonitorData 章节。
  • CanBeSourceOnSound 决定源插件是否可为声音的音频源。
  • CanBeInsertEndOfPipeline 决定效果器是否只能用在音频管线的末端,相当于顶层 Audio Bus 的最后一个效果器插槽(预留给 Audiokinetic 使用)。

在 Wwise 中,您的插件只可用于指定的平台。

另外,也可选择添加 Any 平台,而无需列出所有支持的平台。不过,这样的话会在 Wwise 中将此插件报告为适用于所有平台。若该插件没有提供匹配的运行时库,则用户只有在对应平台上设置端口时才会注意到。

<PlatformSupport>
<Platform Name="Any">
<CanBeInsertOnBusses>true</CanBeInsertOnBusses>
<CanBeInsertOnAudioObjects>true</CanBeInsertOnAudioObjects>
<CanBeRendered>true</CanBeRendered>
</Platform>
</PlatformSupport>

属性要素

每个音频插件都可定义属性和引用。有关属性和引用的更多信息,请参照 Plug-in 属性和自定义属性 XML 描述

内部对象

InnerTypes 部分定义了插件内您可以实例化和使用的可能内部对象类型。可以在 InnerTypes 部分定义多个 InnerType 。每个 InnerType 必须具有唯一名称和插件 ID。InnerType 部分包含 Properties 部分,您可以使用定义插件属性的相同方式定义其属性。

当插件中需要多个对象实例时,Inner Types 非常实用。例如,当具有不定数量的 EQ Band 时,就可以为 EQ 插件定义 Inner Type Band 。每个 and 拥有相同的属性定义,但值不同。

<PluginModule>
<EffectPlugin ...>
<PluginInfo ...>
...
</PluginInfo>
<Properties>
...
</Properties>
<InnerTypes>
<InnerType Name="Band" CompanyID="X" PluginID="Y">
<Properties>
...
</Properties>
</InnerType>
</InnerTypes>
</EffectPlugin>
备注: Inner Types 的属性不支持 RTPC。因此将不能使用 SupportRTPCType 属性和 AudioEnginePropertyID 元素。
备注: 只有音频插件内支持 InnerTypes

若要在插件代码中操纵 Inner Type 实例 (Inner Object),则需获取插件类中的 AK::Wwise::Plugin::RequestObjectStore ,并使用 AK::Wwise::Plugin::ObjectStore m_objectStore 成员,以此请求服务。 AK::Wwise::Plugin::ObjectStore 接口提供用于创建和删除 Inner Object 的函数(AK::Wwise::Plugin::ObjectStore::CreatePropertySetAK::Wwise::Plugin::ObjectStore::DeletePropertySet )。 Inner Object 的属性使用 PropertySet 接口操纵(参见 Property Set 章节)。

在创建对象后,须使用插入函数 (AK::Wwise::Plugin::ObjectStore::InsertPropertySet) 和移除函数 (AK::Wwise::Plugin::ObjectStore::RemovePropertySet) 将其存储到命名列表中。 例如,您可以创建类型为 Band 的内部对象,并将它存储在 BandList 中:

// Create a new band
AK::Wwise::Plugin::PropertySet* pBand = m_objectStore->CreatePropertySet("Band");
// 在“BandList”中插入新 band(位于末尾)
m_objectStore->InsertPropertySet("BandList", (unsigned int)-1, pBand);
备注: 每次只能将 Inner Object 存储到一个列表中。

工程 Work Unit 中数据的存留由 Wwise 自动处理。不过,用户须针对 SoundBank 和声音引擎数据实现 Inner Object 的序列化。须将 AK::Wwise::Plugin::CustomData::GetPluginDataAK::Wwise::Plugin::AudioPlugin::GetBankParameters 中的内部对象进行序列化。

在向对象库中添加内部对象时,Wwise 会自动创建相关的撤消机制, 您无需亲自实现撤消系统。但为了正常地支持撤消事件,您只需在收到框架通知时更新用户接口即可。

Inner Object 通知

AK::Wwise::Plugin::NotificationsObjectStore 接口提供所要覆盖的处理程序,以便对与 Inner Object 相关的通知事件作出响应。这些主要是为了基于模型更改来更新自定义 GUI 元素。用户交互、撤消事件甚至 WAAPI 调用都可能会触发这类更改。

比如,在调用 AK::Wwise::Plugin::ObjectStore::InsertPropertySet 后,不要马上更新 UI。 而应等待您的插件上调用通知 AK::Wwise::Plugin::NotificationsObjectStore::NotifyInnerObjectAddedRemoved。 此通知告诉您对象已添加到列表或者已从列表中移除。

同样地,您也可以对 AK::Wwise::Plugin::NotificationsObjectStore::NotifyInnerObjectPropertyChanged 作出响应。在 Inner Object 中发生属性值更改时会调用此函数。

故障排除

如果您遇到任何问题,请参阅 Wwise 源插件和效果器插件故障排除指南

AkForceInline void Max(AkReal32 *in_pVolumesDst, const AkReal32 *in_pVolumesSrc, AkUInt32 in_uNumChannels)
Get max for all elements of two volume vectors, independently.
AkForceInline void Min(AkReal32 *in_pVolumesDst, const AkReal32 *in_pVolumesSrc, AkUInt32 in_uNumChannels)
Get min for all elements of two volume vectors, independently.