WWise is Audiokinetic’s cross-platform audio engine that interacts well with game engines, allowing audio designers to handle audio solely within WWise. This separates game logic from audio production and management, providing events and parameters for use in game engines, achieving decoupling with business logic and precision control over audio.
This article mainly introduces the integration of WWise with UE4, remote building, resource analysis, documentation collection, the control interaction between WWise and UE, and code analysis of generated Banks.
Integration into UE4
WWise supports all platforms, including Linux/Lumin/PS4/Switch/XboxOne/Windows/Android/iOS/Mac. However, most games do not require support for so many platforms, and the WWise link library is large. Therefore, I’ve trimmed down the official multi-platform version by removing support for the following platforms:
- Linux
- Lumin
- PS4
- Switch
- XboxOne
For the Android and Windows platforms, the following adjustments were made:
- Removed support for arm64-v8a and android_x86/x86_64 link libraries
- Removed all link libraries for Win32/removed support for vc140/vc150
For iOS, the following adjustments were made:
- Removed all iphonesimulator, saving 2.31G of space
For Mac support:
The current project does not require support for Mac (using iOS for remote builds), but to avoid issues with compiling the project on Mac, the Mac link library and module support have been retained, and keeping it will not affect the packaging for Android/iOS.
Link Libraries
In the trimmed version, I support the following platforms:
- Android_armabi_v7a
- iOS
- Mac
- Win vc160
Each platform supports Debug
/Profile
/Release
, corresponding to UE’s Debug
/Development
/Shipping
configuration.
In the Android Development configuration, including the WWise link library, the APK size increases by approximately 30M.
WWise Version Issues
The WWise version is Wwise 2019.1.9.7221
In AkAudio_Android.build.cs
, the link library support for Android has a path error under UE_4_25_OR_LATER
.
Original path:
1 | Path.Combine(ThirdPartyFolder, "Android", "armeabi-v7a", akConfigurationDir, "lib") |
Actual path:
1 | Path.Combine(ThirdPartyFolder, "Android_armeabi-v7a", akConfigurationDir, "lib") |
However, this modification will result in link errors when simultaneously supporting armv7 and arm64. The solution is discussed in the next section.
Android Support for armv7 and arm64
When supporting both arm64
and armv7
in the UE project settings for Android, the above modifications result in link errors. It is necessary to change the link library paths in WWise. For specific methods, refer to my note: Simultaneously Supporting armv7 and arm64 Link Libraries.
Copying Android Link Libraries
The WWise SDK simultaneously uses UPL and RuntimeDependencies to add link libraries, causing duplication. Therefore, you can remove the moving platform entries from RuntimeDependencies:
1 | public AkAudio(ReadOnlyTargetRules Target) : base(Target) |
Remote Building for iOS
In my previous notes, I mentioned that remote building for iOS involves uploading files to Mac for compilation. However, a problem arises if the files involved in the build are not uploaded to Mac, which unfortunately occurs with WWise. The solution is to upload the files that WWise depends on to Mac.
Since UE uses RSync
for file synchronization between the build machine and local files, I previously discussed this in the article UE4 Development Notes: Mac/iOS Section # Configuring Remote Builds, you can create a file <ProjectDir>/Build/Rsync/RsyncProject.txt
to write RSync’s file synchronization rules, uploading the required files to Mac.
The rules for WWise are as follows:
1 | + /Plugins/Wwise/ThirdParty/include/** |
This just specifies that the WWise link library and Include directories are fully uploaded to Mac.
WWise Resources
WWise has two resource formats in UE: one is UAkAudioEvent
, used to execute specified Events in WWise, and the other is UAkAudioBank
, which records which Events are included in the Bank, marking them to be packed together during generation.
UAkAudioEvent
UAkAudioEvent
: Its main function is to designate the Bank for the current Event. Its only function is LoadBank
, which loads the Bank specified for the current Event (if you see its usage, it’s just to retrieve its name). The WWise integration into UE’s plugin also binds the UAkAudioEvent
object’s name to the UAkAudioBank
for generating bnk files, which is why the naming of resources in UE must exactly match the naming of Events in WWise.
1 | UCLASS(meta=(BlueprintSpawnableComponent)) |
By obtaining the name of the Event and passing it to the deeper PostEvent:
1 | int32 UAkGameplayStatics::PostEvent( |
UAkAudioBank
UAkAudioBank
is used to call AkAudioDevice
to load the Bank. If AutoLoad is enabled in UE, it will execute the loading in the UObject’s PostLoad
.
The official introduction to SoundBanks can be found here: SoundBank
1 | /** |
Moreover, LoadBank similarly uses the Event name for passing to FAkAudioDevices
.
Analysis of Bank Generation
So how does AkAudioEvent
associate with SoundBank
? In the code, I see the need for LoadBank
, but I don’t see where SoundBank
and Event are associated in UE resources, and the naming of SoundBank has no relation in WWise.
The answer lies in the files generated by AkSoundBank
. When generating AkSoundBank
resources with Generate Selected SoundBank
:
It creates the following files under the WwiseSoundBankFolder
directory in project settings:
1 | D:\WWise\WwiseDemoGame\Content\WwiseAudio\Windows>tree /a /f |
Among them, the four Init.* files are essential for Init’s Bank content. Each Bank generates four files: .bnk
/.json
/.txt
/.xml
, where the .bnk
file is what UE needs to load the bank, and tests show that deleting the other files does not cause any issues.
- bnk: Data file, *.Bnk stores detailed event information, audio, and data structures required by other plugins. It can be simply understood as a container for storing data, allowing dynamic control over adding and unloading during runtime.
- json: Descriptor file for recording what data and Events are in the current bank and the corresponding Event’s path in the WWise project.
1 | { |
- xml: Descriptor file containing the same information as json.
1 |
|
- txt: Also a descriptor file, but with fewer details compared to json and xml.
1 | Event ID Name Wwise Object Path Notes |
The similar Post*
actions in UAkGameplayStatics
where the Actor is passed function to get the World, and then retrieve AkComponent
from that Actor (if it doesn’t exist, create it and attach it to the Actor’s RootComponent):
1 | struct AkDeviceAndWorld |
Using the Event to specify the SoundBank, executing Generate Selected Bank
workflow is as follows:
- Get the list of names of the selected SoundBank
- Retrieve all
UAkAudioEvent
objects in the engine and analyze if the names ofRequireBank
fromAkSoundEvent
match the names obtained from the first step, thereby getting allAkAudioEvents
in the SoundBank; - Based on the results of the above two analyses, generate
SoundBankDefinitionFile
, which is stored in the UE project directory, namedTempDefinitionFile.txt
1 | VelocityBank "PlayRederenceSoundTest" |
This records the association between UE’s SoundBank objects and their associated Event
as well as Bus
names, passed to WwiseCLI.exe
using the -ImportDefinitionFile
parameter, allowing WWise to understand the correspondence between UE’s SoundBank and Event.
- On the WWise side, based on the
ImportDefinitionFile
, it matches with Events and Bus in the WWise project, creating a SoundBank that contains the specified Events and generates json/xml/txt descriptor files.
The loading process for UE using LoadBank
should be:
- Retrieve the Bank’s name via the Bank object.
- Look for the corresponding
bnk
file in theWwiseSoundBankFolder
directory based on the Bank name. - Obtain the
bnk
file and proceed with loading.
Interaction Between UE and WWise
In UE, the use of WWise API to play and control sound is introduced.
PlaySoundAtLocation
The APIs are available in UAkGameplayStatics
:
1 | /** Posts a Wwise Event at the specified location. This is a fire and forget sound, created on a temporary Wwise Game Object. Replication is also not handled at this point. |
These two APIs can be used to play sounds at a specified location by passing resources of AkAudioEvent
or the Event name. PostEventAtLocationByName
is a wrapped version of UAkGameplatStatics::PostEventAtLocation
, with AkAudioEvent being NULL.
PostEvent
Sends a specified Wwise Event bound to the root component of the given Actor. If the incoming Actor does not have an AkComponent
attached, one will be created on PostEvent and will be attached by default to that Actor’s RootComponent.
After PostEvent
, if subsequent control of Event values is needed, like RTPC or Switch, the corresponding Actor must be passed in (since PostEvent essentially works through AkComponent
):
1 | AkPlayingID FAkAudioDevice::PostEvent( |
Currently, my understanding is that the Actor (with AkComponent) passed in serves as context for playing sounds in WWise, allowing further operations to control specific events through this context.
Furthermore, PostEvent has various types of callback functions, controlled through the mask values passed in, defined by the EAkCallbackType
enum (bitmask):
1 | static int32 PostEvent( class UAkAudioEvent* AkEvent, |
Available values for EAkCallbackType
:
1 | /// Type of callback. Used as a bitfield in methods AK::SoundEngine::PostEvent() and AK::SoundEngine::DynamicSequence::Open(). |
- EndOfEvent: Triggered when the event ends; can be cast to AkEventCallbackInfo
- Marker: Triggered when encountering a marker; can be cast to AkMarkerCallbackInfo
- Duration: Triggered when the Sound Engine knows the current sound duration; can be cast to AkDurationCallbackInfo
- Starvation: Triggered when playback skips a frame due to stream starvation; can be cast to AkEventCallbackInfo
- MusicPlayStarted: Triggered when a Play or Seek command is executed (Seek commands are issued from AK::SoundEngine::SeekOnEvent); applicable to objects in the Interactive-Music Hierarchy only; can be cast to AkEventCallbackInfo
- MusicSyncBeat: Enable notifications on Music beat; can be cast to AkMusicSyncCallbackInfo
- MusicSyncBar: Enable notifications on Music Bar; can be cast to AkMusicSyncCallbackInfo
- MusicSyncEntry: Enable notifications on Music Entry; can be cast to AkMusicSyncCallbackInfo
- MusicSyncExit: Enable notifications on Music Exit; can be cast to AkMusicSyncCallbackInfo
- MusicSyncGrid: Enable notifications on Music Grid; can be cast to AkMusicSyncCallbackInfo
- MusicSyncPoint: Enable notifications on Music switch transition synchronization point; can be cast to AkMusicSyncCallbackInfo
- MIDIEvent: Enable notifications for MIDI events; can be cast to AkMIDIEventCallbackInfo
Marker
Audio added in the Sound VFX
in the WWise editor can be edited to add Markers, which can be received in UE by setting the CallbackMask
parameter to EAkCallbackType::Marker
when calling UAkGameplayStatics::PostEvent
. This allows receiving the location of each Marker hit during playback for performing game logic actions, such as displaying audio subtitles.
Listening in UE:
Moreover, the Identifier
also starts from 0:
Adding Markers in WWise:
In UE, when PostEvent
, the value of the CallbackMask
can be added along with Marker
, allowing for receiving each encountered marker during playback in the associated event, useful for displaying subtitles while playing.
RTPC
Real-time Parameter Controls (RTPC) allow real-time control of specific properties of various Wwise objects (including sound objects, containers, buses, effects, etc.) based on real-time parameter changes occurring in the game.
RTPC can transfer values from the program to the WWise side, allowing WWise to control the sound based on the incoming values.
In WWise, RTPC:
Switch
Switches can be used in the engine to switch different modes, such as the sounds of players walking on different surfaces.
In PostEvent
one AkEvent
, the SwitchGroup
and SwitchState
can be passed along with the Actor passed at the time of PostEvent.
Sequencer
WWise provides support for use in Sequencer, enabling the use of AkAudioEvents
and AkAudioRTPC
to play and control Events within a Sequence.
Animation
And can be used in animation notifications:
Specify the Event for the notification:
## CommandLet
WWise provides Commandlet in UE for handling the batch generation of Banks.
Introduction to usage:
1 | Commandlet allowing to generate Wwise SoundBanks. |
The Commandlet for generating SoundBank is:
1 | Engine/Binaries/Win64/UE4Editor.exe "D:/WwiseDemoGame.uproject" -run=GenerateSoundBanks -platforms=Windows,Android,iOS -wait |
The -wait
parameter is included in the CommandLet to control waiting for user input after execution is complete, preventing the execution window from flashing and disappearing. When no specific SoundBank is designated for generation, all defined SoundBanks in the project will be generated. If you want to specify, you can use the format -banks=aaa,bbb,ccc
and so on.
The final execution command is (you can see the -ImportDefinitionFile
parameter):
1 | "C:\Program Files (x86)\Audiokinetic\Wwise 2019.1.9.7221\Authoring\x64\Release\bin\WwiseCLI.exe" "D:/WwiseDemoGame/UnrealWwiseDemo/UnrealDemo.wproj" -GenerateSoundBanks -Bank ExtSrcBnk -Bank AmbientBank -Bank ReverbBank -Bank VelocityBank -Bank MatineeBank -Bank SubtitleBank -Bank SwitchBank -ImportDefinitionFile "D:/WwiseDemoGame/TempDefinitionFile.txt" -Platform Windows -SoundBankPath Windows "D:\WwiseDemoGame\Content\WwiseAudio\Windows" -Platform Android -SoundBankPath Android "D:\WwiseDemoGame\Content\WwiseAudio\Android" -Platform iOS -SoundBankPath iOS "D:\WwiseDemoGame\Content\WwiseAudio\iOS" |
Breaking down the command:
- Path to WWiseCLI.exe
-GenerateSoundBanks
: Passed to WWiseCLI.exe indicating the function to generate SoundBank-Bank
: Specify the name of the Bank-ImportDefinitionFile
: Specify theTempDefinitionFile.txt
-Platform
: Specify the platform-SoundBankPath
: Specify the directory where the platform’s generated content will be saved
Command Line Parameters
-nosound
: Disable sound in WWise.
1 | bool FAkAudioDevice::EnsureInitialized() |
Global Pause Music
This can be achieved with the following code:
1 | // on enter background |
Hot Updating WWise’s Banks
From the above analysis, it can be seen that WWise generates Banks on a per-platform basis, creating corresponding folders for each platform. This requires us to include different external files based on different platforms during hot updates. HotPatcher already supports this feature, enabling specific platforms to contain special files.
Disadvantages of WWise Integration into UE
The official importation of Events and the process of specifying Banks is too cumbersome; each Event must be dragged into the Content Browser to create UE Event resources, followed by manually specifying RequireBank, which is quite troublesome. In fact, the WWise editor itself contains the functionality for Bank editing, but there is no official method provided in UE for batch generation of Event and Bank resources. This can be a point for amateur extension development, creating a batch import feature; this is a later topic, to be tackled when time permits.
Documentation
- Overview of concepts in WWise: Overview of Wwise Concepts
- DLC Considerations and Limitations