集成 Wwise 声音引擎的第一步是在游戏启动时正确初始化构成声音引擎的各种模块。
在本示例工程中,定义了以下函数来执行与声音引擎初始化相关的一切操作:
bool InitSoundEngine() { ... 在此执行初始化... return true; }
在主函数的开头调用它。让我们查看一下需要初始化的各项:
链接了 Wwise 声音引擎的每个工程必须定义多个挂钩。然后可以使用它们监控对内存存取访问的调用。
///////////////////////////////////////////////////////////////////////////////// // 自定义分配/释放函数。它们在 AkMemoryMgr.h 中被声明为“extern”, // 必须由游戏程序员定义。 ///////////////////////////////////////////////////////////////////////////////// namespace AK { #ifdef WIN32 void * AllocHook( size_t in_size ) { return malloc( in_size ); } void FreeHook( void * in_ptr ) { free( in_ptr ); } // 注:Stream Manager 默认实现的 I/O 池可以使用 VirtualAllocHook() // 来支持“真正的”非缓冲 I/O(使用 FILE_FLAG_NO_BUFFERING // - 请参阅 Windows SDK 文档了解更多详情)。这不是强制要求; // 您可以使用一个简单的 malloc() 来实现它。 void * VirtualAllocHook( void * in_pMemAddress, size_t in_size, DWORD in_dwAllocationType, DWORD in_dwProtect ) { return VirtualAlloc( in_pMemAddress, in_size, in_dwAllocationType, in_dwProtect ); } void VirtualFreeHook( void * in_pMemAddress, size_t in_size, DWORD in_dwFreeType ) { VirtualFree( in_pMemAddress, in_size, in_dwFreeType ); } #endif }
///////////////////////////////////////////////////////////////////////////////// // 自定义分配/释放函数。它们在 AkMemoryMgr.h 中被声明为“extern”, // 必须由游戏程序员定义。 ///////////////////////////////////////////////////////////////////////////////// namespace AK { #ifdef AK_APPLE void * AllocHook( size_t in_size ) { return malloc( in_size ); } void FreeHook( void * in_ptr ) { free( in_ptr ); } #endif }
///////////////////////////////////////////////////////////////////////////////// // 自定义分配/释放函数。它们在 AkMemoryMgr.h 中被声明为“extern”, // 必须由游戏程序员定义。 ///////////////////////////////////////////////////////////////////////////////// namespace AK { #ifdef AK_APPLE void * AllocHook( size_t in_size ) { return malloc( in_size ); } void FreeHook( void * in_ptr ) { free( in_ptr ); } #endif }
第一个您必须初始化的组件是 Memory Manager(内存管理器)。以下代码使用二十个内存池来创建默认 Memory Manager:
#include <AK/SoundEngine/Common/AkMemoryMgr.h> // Memory Manager #include <AK/SoundEngine/Common/AkModule.h> // 默认内存和流管理器 (...) bool InitSoundEngine() { // // 创建和初始化默认内存管理器。注意, // 可以使用您自己的内存管理器覆盖默认内存管理器。请参阅 // SDK 文档了解更多信息。 // AkMemSettings memSettings; memSettings.uMaxNumPools = 20; if ( AK::MemoryMgr::Init( &memSettings ) != AK_Success ) { assert( !"Could not create the memory manager." ); return false; } (...) }
![]() |
Note: 您可以覆盖 Memory Manager,在这种情况下,必须根据需要修改上述代码。请参阅 取代内存管理器 了解更多信息。 |
请参阅 Memory Manager 了解有关 Memory Manager 的更多详情。
Memory Manager 一旦初始化,我们就可以继续初始化 Streaming Manager 了。
以下代码对默认 Streaming Manager 进行初始化。它需要一个 AK::StreamMgr::IAkFileLocationResolver 实例,并创建流播放设备。这就需要一个 AK::StreamMgr::IAkIOHookBlocking 或 AK::StreamMgr::IAkIOHookDeferred 实例,具体取决于流播放设备调度程序类型(AK_DEVICE_BLOCKING 或 AK_DEVICE_DEFERRED_LINED_UP)。这些接口在 AkStreamMgrModule.h 中定义,其中包含针对 SDK 中默认 Stream Manager 实现的所有定义。
对于磁盘 I/O,集成声音引擎的推荐方式是使用默认 Stream Manager 实现,并实现 AkStreamMgrModule.h 中定义的接口。这些接口构成了 Low-Level I/O 子模块。请参阅 流播放/流管理器 了解更多信息。
本例中按原样使用了 CAkFilePackageLowLevelIOBlocking 示例。此类用于实现 AK::StreamMgr::IAkFileLocationResolver 和 AK::StreamMgr::IAkIOHookBlocking 接口,能够加载由 File Packager 实用程序生成的文件包(请参阅 文件包底层 I/O 实现 和 File Packager 实用程序 了解有关 File Packager 及其在 Low-Level I/O 中的工作方式的更多信息)。
请参阅 Low-Level I/O 了解有关 Low-Level I/O 的更多信息。
#include <AK/SoundEngine/Common/IAkStreamMgr.h> // Streaming Manager #include <AK/Tools/Common/AkPlatformFuncs.h> // 线程定义 #include <AkFilePackageLowLevelIOBlocking.h> // Low-Level I/O 实现示例 (...) // 我们使用作为 SDK 代码示例一部分的 // 默认 Low-Level I/O 实现,文件包扩展名为 CAkFilePackageLowLevelIOBlocking g_lowLevelIO; (...) bool InitSoundEngine() { (...) // // 创建并初始化默认 Streaming Manager 实例。注意, // 可以使用您自己的流管理器覆盖默认流管理器。请参阅 // SDK 文档了解更多信息。 // AkStreamMgrSettings stmSettings; AK::StreamMgr::GetDefaultSettings( stmSettings ); // 在此自定义 Stream Manager 设置。 if ( !AK::StreamMgr::Create( stmSettings ) ) { assert( !"Could not create the Streaming Manager" ); return false; } // // 创建采用阻塞型 Low-Level I/O 握手机制的 Streaming Manager。 // 注意,可以使用您自己的 Low-Level I/O 模块覆盖默认的 Low-Level I/O 模块。请参阅 // SDK 文档了解更多信息。 // AkDeviceSettings deviceSettings; AK::StreamMgr::GetDefaultDeviceSettings( deviceSettings ); // 在此自定义流播放设备设置。 // CAkFilePackageLowLevelIOBlocking::Init() 在 Stream Manager 中 // 创建流播放设备,并将其自身注册为 File Location Resolver 。 if ( g_lowLevelIO.Init( deviceSettings ) != AK_Success ) { assert( !"Could not create the streaming device and Low-Level I/O system" ); return false; } (...) }
有关默认 Stream Manager 和流播放设备初始化设置的更多信息,请参阅 Audiokinetic Stream Manager 初始化设置 。
![]() |
Caution: 某些初始化设置使用针对特定平台的成员结构,例如 AkThreadProperties。 |
如果您决定覆盖默认的 Low-Level I/O 实现或者整个 Streaming Manager,需要相应地修改此代码。请参阅 流播放/流管理器 了解更多信息。
现在基本模块已经初始化,下面我们可以对声音引擎本身进行初始化了:
#include <AK/SoundEngine/Common/AkSoundEngine.h> // 声音引擎 (...) bool InitSoundEngine() { (...) // // 使用默认初始化参数 // 创建声音引擎 // AkInitSettings initSettings; AkPlatformInitSettings platformInitSettings; AK::SoundEngine::GetDefaultInitSettings( initSettings ); AK::SoundEngine::GetDefaultPlatformInitSettings( platformInitSettings ); if ( AK::SoundEngine::Init( &initSettings, &platformInitSettings ) != AK_Success ) { assert( !"Could not initialize the Sound Engine." ); return false; } (...) }
有关如何初始化声音引擎的更多信息,请参阅 高级声音引擎集成
如果您的工程使用互动音乐功能,在声音引擎之后必须对音乐引擎进行初始化。
#include <AK/MusicEngine/Common/AkMusicEngine.h> // 音乐引擎 (...) bool InitSoundEngine() { (...) // // 使用默认初始化参数 // 对音乐引擎初始化 // AkMusicSettings musicInit; AK::MusicEngine::GetDefaultInitSettings( musicInit ); if ( AK::MusicEngine::Init( &musicInit ) != AK_Success ) { assert( !"Could not initialize the Music Engine." ); return false; } (...) }
如果您希望使用 Wwise 创作应用程序来连接游戏并进行游戏内混音、性能分析和故障排除,下一步就要对通信功能进行初始化。强烈建议这样做,因为游戏内混音、性能分析和故障排除是声音设计师高效处理游戏音频的强大武器。
![]() |
Note: 要使用通信功能,您需要与 CommunicationCentral 模块建立链接。 |
![]() |
Note: 通信功能只有在声音引擎的 Debug 和 Profile 配置中才可用。游戏的零售版中不需要通信功能,因此声音引擎的发布版本中没有这一功能。以下代码使用 AK_OPTIMIZED 符号将通信相关代码排除在发布版本之外。 |
// 为允许 Wwise 和游戏之间进行通信,包含以下代码——发布版本不需要 #ifndef AK_OPTIMIZED #include <AK/Comm/AkCommunication.h> #endif // AK_OPTIMIZED (...) bool InitSoundEngine() { (...) #ifndef AK_OPTIMIZED // // 对通信进行初始化(在发布版本中无此步骤!) // AkCommSettings commSettings; AK::Comm::GetDefaultInitSettings( commSettings ); if ( AK::Comm::Init( commSettings ) != AK_Success ) { assert( !"Could not initialize communication." ); return false; } #endif // AK_OPTIMIZED (...) }
现在您已将声音引擎的所有模块初始化。然后应注册插件(请参阅 插件示例 )。请参阅 创建重复调用来执行音频处理 详细了解您在游戏循环中用于处理音频的、必须执行的调用。
有些控制台通信库不能正确地平衡初始化/终止调用;因此,调用 AK::Comm::Term 将终止控制台的底层通信库。这将关闭游戏的所有 TCP/IP 通信。如果您的游戏需要在终止后使通信库保持启用状态,AkCommSettings(结合 Ak::Comm:Init 使用)具有可供选择是否将系统库初始化的参数。如果您选择自己将通信库初始化,则请参照 Wwise 声音引擎的以下代码。游戏中应执行类似的代码。
Windows 套接字初始化:
WSAData wsaData = { 0 }; ::WSAStartup( MAKEWORD( 2, 2 ), &wsaData )
终止:
::WSACleanup();
AkCommSettings 结构的 AkCommSettings::ports 成员代表 Wwise 创作应用程序与声音引擎之间进行通信所使用的网络端口。当 Wwise 通信功能启用时,所有这些端口在游戏中都会打开。
其中 AkCommSettings::Ports::uDiscoveryBroadcast 端口不是动态的(不能设置为 0)。Wwise 创作应用程序需知道该端口才能在网络上发现游戏。另外,此处的指定值必须是创作应用程序 Project Settings 的 Network 选项卡中指定的值。
![]() |
Tip: 如果您的团队正在使用 Wwise 制作多款游戏,可以为每款游戏使用不同的 Discovery Broadcast 端口。通过这种方法,在 Wwise 创作应用程序中打开 Remote Connections 窗口时,只有对应当前 Wwise 工程的游戏才会被列出。更改此端口时,请确保在创作应用程序的 Project Settings 中和游戏中传递给 AK::Comm::Init() 的 AkCommSettings 结构中一起更改。 |
结构中的另外两个端口可以是动态的(或者“临时的”)。这意味着,操作系统使用的不是固定端口,而是自动选择一个端口:
在默认情况下这些端口都是动态的。建议将它们保持动态状态,使其与其他应用程序发生冲突的机率最小化。
Wwise 要使用三个顺序通道才能正常工作,并且它们必须按照在端口结构中出现的顺序排序。在 Wwise 中,您可以选择基本端口(在默认情况下为 8)。
如果它们与游戏其他组件使用的端口发生冲突,只需在调用 AK::Comm::Init() 前在 AkCommSettings 结构中更改它们即可。
![]() |
Note: 在多平台游戏中,可以在不同的平台上对 AkCommSettings::Ports::uCommand 和 AkCommSettings::Ports::uNotification 使用不同的端口。 |
![]() |
Tip: 有关动态/临时端口的更多信息,请查阅以下网站: |
Wwise 通信中还涉及另一个端口,但它只在创作应用程序中打开,因此不是 AkCommSettings::Ports 结构的一部分。
创作应用程序使用该端口来接收针对 Discovery Broadcast 消息的响应,这些消息用于检测网络上运行的游戏。它在默认情况下是动态的(设置为 0),但可以在创作应用程序的 Project Settings 中进行更改。