You control playback in the Wwise sound engine with Events and Game Syncs. These elements refer to internal sound structures stored in SoundBanks, which ultimately refer to loose media files. All of these must be loaded by the sound engine before using them.
You can load a SoundBank either implicitly or explicitly. Both approaches, detailed below, offer different option with implicit advantages and disadvantages that need to be evaluated for your particular scenario.
You can load a SoundBank explicitly by using one of the AK::SoundEngine::LoadBank() methods of the sound engine API. After a SoundBank is loaded, all the objects within it are ready to be used.
In the following example, the SoundBank BANK_01 is loaded explicitly. It is identified by an ID, which is defined in the Wwise_IDs.h header file. For a discussion on identifying SoundBanks using strings (Unicode or ANSI) or IDs, refer to Identifying Banks ). It contains the Event PLAY_SOUND_01, along with its associated sound structures and media (consult the Wwise Help for more information on generating SoundBanks with Wwise). When it is loaded, the Event is posted to the sound engine.
|
Note: The sound data is stored in a memory pool that is created automatically for this purpose. Refer to the section Memory Usage for details on memory usage. |
#include "Wwise_IDs.h" // ... AkGameObjectID gameObj = 3; AK::SoundEngine::RegisterGameObj( gameObj ); // Load a bank synchronously, using its ID. AkBankID returnedBankID; AKRESULT eResult = LoadBank( AK::BANKS::BANK_01, // Identifier of the bank to be loaded. AK_DEFAULT_POOL_ID, // Memory pool ID (data is written in the default sound engine memory pool when AK_DEFAULT_POOL_ID is passed). returnedBankID // Returned bank ID. ); if( eResult != AK_Success ) { // Failed loading bank. // Handle error... } // Load succeeded. // Use the bank as required... // For example, if the bank contained the event PLAY_SOUND_01, along with its // associated sound structures and media. AK::SoundEngine::PostEvent( AK::EVENTS::PLAY_SOUND_01, // Unique ID of the event gameObj // Associated game object ID );
The PrepareEvent/PrepareGameSync API allows for implicit loading of media that is not included in a SoundBank. In order to do this, you must first explicitly load a SoundBank that contains the definition of the Events and/or Game Syncs, through LoadBank(). Typically, these SoundBanks will contain only Events and structures, but no media, and thus be very lightweight. Refer to the Wwise Help to know how you can define a SoundBank that has no media data. When the referenced media is not included in the SoundBank, then it must be available as loose media files in the file system. After the definitions of Events and Game Syncs are loaded, you must then "prepare" them in order to use them (AK::SoundEngine::PrepareEvent() and AK::SoundEngine::PrepareGameSyncs()). When events or game syncs are prepared, then the sound engine will implicitly fetch the referenced media files from the file system. It is possible to include sound structures in a different SoundBank than the event definitions. The Event SoundBank will then contain a reference to the banks that contain the structures data, and the structures from the referenced SoundBank will be implicitly loaded along with the media when the Event is prepared. All contained structures will be loaded from the linked SoundBank and not just the ones that are referenced by the Event, and for this reason it is usually more practical to bundle the Events and structures in the same SoundBank.
In the following example, the bank BANK_02 is loaded explicitly and its referenced media is loaded implicitly. It contains the definition of the event PLAY_SOUND_02 and the related sound structures. Since it does not contain the event's associated media, posting the event will fail unless it is prepared first. Therefore, after loading the bank successfully, the event is prepared prior to posting. When an event is prepared, the sound engine will automatically load all the media required to post the event successfully.
#include "Wwise_IDs.h" // ... AkGameObjectID gameObj = 3; AK::SoundEngine::RegisterGameObj( gameObj ); // Load a bank synchronously, using its ID. // This bank may contain only the definition of the events you wish to use. AkBankID returnedBankID; AKRESULT eResult = LoadBank( AK::BANKS::BANK_02, // Identifier of the bank to load. AK_DEFAULT_POOL_ID, // Memory pool ID (data is written in default sound engine memory pool when AK_DEFAULT_POOL_ID is passed). returnedBankID // Returned bank ID. ); if( eResult != AK_Success ) { // Failed loading bank. // Handle error... } // Load succeeded. The definition of the event PLAY_SOUND_02 and its related structures are loaded. // In order to post the event, it needs to be prepared (here, synchronously). AkUniqueID eventToPrepare = AK::EVENTS::PLAY_SOUND_02; eResult = PrepareEvent( Preparation_Load, // Preparation type: load. &eventToPrepare, // Array of event IDs. 1 // Number of event IDs in the array. ); if ( eResult != AK_Success ) { // Failed preparing event. // Handle error... } // Prepare event succeeded: the sound engine has gathered all the media (and sound // structures if necessary) that are required to successfully post the event, by loading all // necessary media under the hood. // Post the event. AK::SoundEngine::PostEvent( AK::EVENTS::PLAY_SOUND_02, // Unique ID of the event gameObj // Associated game object ID );
To get a more complete example on how to use AK::SoundEngine::PrepareEvent and AK::SoundEngine::PrepareGameSyncs, refer to sections:
Bank loading is performed in a separate thread of the sound engine. All LoadBank(), PrepareEvent() and PrepareGameSyncs() functions of the main API are available through synchronous and asynchronous loading schemes.
Synchronous AK::SoundEngine::LoadBank() functions are blocking functions. They return either when the bank is loaded, or if an error occurs.
Asynchronous AK::SoundEngine::LoadBank() functions return immediately and the callback function is called after the requested action is completed, with a cookie as a parameter. When a call is asynchronous, error handling must be performed in the callback function.
The cookie parameter is optional and is available for your convenience. If you are not using it, just pass NULL. The sound engine will not use this pointer; it will simply return it with the callback function.
Callback functions used with asynchronous versions of LoadBank(), UnloadBank(), PrepareEvent() and PrepareGameSyncs() must follow this prototype:
typedef void( *AkBankCallbackFunc )( AkBankID in_bankID, void * in_pInMemoryBankPtr, AKRESULT in_eLoadResult, AkMemPoolId in_memPoolId, void * in_pCookie );
You are responsible for implementing the callback function and, therefore, you must guarantee its validity.
The parameters in_bankID and in_memPoolId are not relevant when receiving callbacks for PrepareEvent and PrepareGameSync and should simply be ignored.
|
Note: The memory pool ID is either AK_DEFAULT_POOL_ID, or the ID of any pool you have created. For more information on the bank memory allocation model, see Memory Usage. |
Refer to AkBankCallbackFunc for definitions of the parameters that are passed to the callback function.
As said previously in Identifying Banks, you can either load banks from file on your side, then provide the appropriate overload of LoadBank() with a pointer and a size, or you specify a bank identifier (ID or string, see discussion above), and let the sound engine load the bank file through the Stream Manager.
Use one of these prototypes of LoadBank() to load a bank from memory:
// Synchronous. AKRESULT LoadBank( void * in_pInMemoryBankPtr, ///< Pointer to the in-memory bank to load AkUInt32 in_uInMemoryBankSize, ///< Size of the in-memory bank to load AkBankID & out_bankID ///< Returned bank ID ); // Asynchronous. AKRESULT LoadBank( void * in_pInMemoryBankPtr, ///< Pointer to the in-memory bank to load AkUInt32 in_uInMemoryBankSize, ///< Size of the in-memory bank to load AkBankCallbackFunc in_pfnBankCallback, ///< Callback function void * in_pCookie, ///< Callback cookie AkBankID & out_bankID ///< Returned bank ID );
The memory is not copied inside the sound engine, therefore you must ensure that it remains valid until the bank is unloaded. Some alignment restrictions may apply based on the platform of the provided memory pointer to which the bank is loaded. On all platforms, the memory must be aligned on AK_BANK_PLATFORM_DATA_ALIGNMENT bytes. Some platforms may have different requirements, so you should check the platform specific SDK documentation.
LoadBank() parses the bank ID stored in the first few bytes of the pointer that is provided, and returns it. Keep the bank ID to unload the bank later.
|
Note: If you choose to perform file I/O on your side, and feed the sound engine with pointers, then you must use explicit bank loading. Implicit bank loading can be unpredictable. Following a PrepareXXXX command, you can never be sure how many banks will be loaded or the memory requirements of these banks. This is why there are no in-memory versions of PrepareEvent and PrepareGameSyncs. |
The sound engine uses the Stream Manager whenever it needs to read from files. Refer to Identifying Banks for a discussion on bank identification and I/O.
You can use the AK::SoundEngine::SetBankLoadIOSettings() function to tweak the behavior of the sound engine's bank loader in regard to the Stream Manager. For more information on I/O, refer to the section Streaming / Stream Manager.
The sound engine parses banks' metadata and creates its objects in the sound engine's default pool.
In explicit LoadBank() functions that involve I/O, the media is read from disk and copied to a memory pool (the in_poolID argument of these functions). If you pass AK_DEFAULT_POOL_ID, a memory pool is created internally for this purpose. For media loaded implicitly through PrepareEvent() and PrepareGameSyncs(), you must specify a custom pool in the initialization settings of the sound engine (AkInitSettings::uPrepareEventMemoryPoolID).
|
Tip: The process of allocating memory pools can be done at game start-up or every time the player enters a new level. The default pool allocation model can be used early in your development cycle, until bank sizes are frozen. This way, you can optimally manage the memory allocated for banks. |
For more information on creating and managing memory pools with the SDK, see Pools.
There are many overloads of UnloadBank() to explicitly unload a bank:
Likewise, use PrepareEvent() function with the Preparation_Unload flag to decrement the reference count of structures and media associated with these events. When the reference count of all objects within a bank that was loaded implicitly drops to 0, it is automatically unloaded.
Also, use PrepareGameSyncs() function with the Preparation_Unload flag to unload media that was loaded for prepared events that can play only when the specified game sync is selected. Note that the game syncs do not have a reference count and calling it once with the Preparation_Unload flag will immediately unload the unreferenced media.
AK::SoundEngine::UnloadBank() functions return the memory pool ID in which the bank was loaded. The memory pool ID is AK_DEFAULT_POOL_ID if the pool was unspecified in the load bank or if the pool did not exist.
|
Note: If a sound referenced by a bank is playing when that bank is unloaded, it will always stop if the bank contains its sound structure. There are chances that the sound will stop if the bank contained only the media, but other loaded banks have the media and sound structure. It will depend on whether the media was played from the data of the former or the latter. Refer to Duplicating Bank Contents. |
|
Note: If events have been used to modify the parameters of this sound (such as a SetVolume event), this information will be removed. If a parameter has been changed using RTPCs, states, or switches, the parameter will be kept in memory and will be automatically applied if the SoundBank is reloaded. |
The following code loads and unloads a bank synchronously, using Unicode string identifiers and the default bank memory allocation. It also loads and unloads banks implicitly through PrepareEvent().
AkBankID bankID; AKRESULT eResult = AK::SoundEngine::LoadBank( L"Bank1.bnk", AK_DEFAULT_POOL_ID, bankID ); if( eResult != AK_Success ) { // Failed loading bank. // Handle error... } // Bank load succeeded. // Prepare an event. const char * pszEvent = "Event1"; eResult = PrepareEvent( Preparation_Load, &pszEvent, 1 ); if( eResult != AK_Success ) { // Failed preparing event. // Handle error... } // Use the event and bank data... // Then, unprepare the event. eResult = PrepareEvent( Preparation_Unload, &pszEvent, 1 ); if( eResult != AK_Success ) { // Failed unpreparing event. // Handle error... } // Unload the bank. // Note: The bank is unloaded using the bank ID returned by LoadBank(). The call // AK::SoundEngine::UnloadBank( L"Bank1.bnk", NULL ); // works too: the sound engine internally converts the "Bank1.bnk" string into the bank ID. eResult = AK::SoundEngine::UnloadBank( bankID, NULL ); if( eResult != AK_Success ) { // Failed unloading bank. // Handle error... }
In addition to the LoadBank() and PrepareEvent() functions, it is also possible to prepare banks. You can prepare banks using either of the following methods:
Both of these methods use the same PrepareBank mechanism with a slightly different implementation, however AkBankContent_All is used in the most common scenarios.
Remember that when using the PrepareEvent or PrepareBank mechanism, you must provide a valid memory pool in which to load the media. This is done by passing the parameter uPrepareEventMemoryPoolID of the structure AkInitSettings to the Sound Engine. See sample in: Method 4: Preparing Events.
Preparing a bank using AkBankContent_All
allows you to overcome some of the drawbacks of the LoadBank() mechanism, while taking advantage of the benefits of the PrepareEvent() mechanism. When using this method, the SoundBanks may still include all content types (events, structure data, and media files), but instead of loading the media files outright, this method loads all media into memory by using a mechanism similar to the prepare event mechanism. When loading media with PrepareBank(), Wwise first checks to see if a media file already exists in memory before loading it. This keeps memory usage at a minimum by avoiding any duplication of media files in memory.
AkBankContent_All is the default loading mechanism for PrepareBank() and will check the bank for media items to load into the prepare pool. If media for a particular event does not exist in the bank, it can be loaded later from a loose file with a call to PrepareEvent().
When using PrepareBank() with AkBankContent_StructureOnly
, the events and structure metadata are loaded from a SoundBank, but the media items contained in the bank are ignored. Because PrepareEvent() must access media as loose files off disk and is unable to read files contained within a SoundBank, AkBankContent_StructureOnly
is only useful if you also plan on loading the SoundBank using some other loading mechanism at some other time. In most scenarios where media will be loaded individually with PrepareEvent(), the media should not be included in the bank and the AkBankContent_StructureOnly
flag will produce the same result as AkBankContent_All
.
One example where the AkBankContent_StructureOnly
flag may be useful is to implement multiple loading configurations. A game may have a "tool mode" that uses PrepareEvent() to load loose files on-demand and a "game mode" that uses LoadBank() to load the same bank in its entirety.
PrepareBank() can be called synchronously or asynchronously from the API, as desired. However, it is not advised to use both AkBankContent_All
and AkBankContent_StructureOnly
on the same bank because, once the media is loaded using AkBankContent_All
, an unload will release everything - events, structure, and media.
Calling the AK::SoundEngine::ClearBanks()
function is useful when you want to reset the content of the sound engine. Note that you do not have to call ClearBanks()
before calling SoundEngine::Term()
. ClearBanks
internally calls AK::SoundEngine::ClearPreparedEvents
.
After this function is called:
Calling the AK::SoundEngine::ClearPreparedEvents() function will unprepare all Events that were prepared up to now, no matter how many times a single event has been prepared. AK::SoundEngine::ClearPreparedEvents()
is internally called when calling AK::SoundEngine::ClearBanks()
.
Each bank can be loaded only once. If you try to explicitly load a bank a second time, it will result in a bank load error.
The Wwise sound engine allows you to have the same Events, sound structures, or media in two or more banks, and have them all loaded at the same time.
|
Note: For AAC and Opus, which do not support media relocation, if a sound that is common to several banks is being played, and the SoundBank from which it is being read is unloaded, this sound's playback will stop. There will be no transition to this sound's instance in one of the other loaded SoundBanks. |
When using PrepareEvent
, media loaded will not be duplicated in memory if different events require the same media content to be loaded. Multiple Events can reference the same media object, and this media object will be unloaded only when all Events that reference it will be unprepared.
Using LoadBank
along with PrepareEvent
to load the same media content may cause media duplication because banks are loaded as an entity when using LoadBank
.
Questions? Problems? Need more info? Contact us, and we can help!
Visit our Support pageRegister your project and we'll help you get started with no strings attached!
Get started with Wwise