Wwise SDK 2025.1.0
|
Some games frequently have to send a high volume of data to the sound engine. For example, games with lots of game objects and game syncs send hundreds of values to the sound engine at regular intervals. Although you can manage this data transfer with the C++ API, a more efficient way to do so is to use the fully asynchronous, C-compatible Command Buffer API.
The Command Buffer API has two primary advantages over the C++ API:
The Command Buffer API works like other command buffer-based APIs, such as Vulkan and DirectStorage. The command buffer is a region of memory that contains a sequential list of instructions for the sound engine. For example, a single command buffer can contain several unrelated commands such as:
After you construct the buffer and submit it to the sound engine, the buffer is added to the sound engine's internal processing queue. The commands in the buffer are then processed asynchronously on the next audio rendering frame, in the order in which they are listed in the buffer.
Commands can fail during processing. When a command fails, the sound engine proceeds to the next command in the buffer.
Clients can be called back when all commands in a buffer are processed. When this callback occurs, the client can inspect the result code of each command in the buffer and release or re-use the memory area.
To construct a command buffer, the size of the buffer must first be determined. The size of the buffer depends on the quantity and type of commands it contains. You can use the AK_CommandBuffer_MinSize()
and AK_CommandBuffer_CmdSize()
functions to calculate the buffer size.
After the buffer size is calculated, the client can allocate the buffer using AK_CommandBuffer_Create()
. This function allocates the buffer and initializes it as an empty but valid command buffer.
For example, the following code demonstrates how to create a valid command buffer able to accomodate 20 RegisterGameObject
commands and 20 SetRTPC
commands:
![]() | 참고: Alternatively, clients can choose to manage the command buffer memory using their own engine's allocation hooks. To do so, replace the call to Note that such buffers should be released using the usual method provided by the game engine. See Cleaning up for more details. |
To add commands to the buffer, use AK_CommandBuffer_Add()
. For example, the following code demonstrates how to fill the buffer with 20 RegisterGameObject
commands and 20 SetRTPC
commands:
Each command has a code (dictated by the enum AkCommand
) and a fixed-size payload structure. Not all commands have the same payload size. The example above shows that the AkCommand_RegisterGameObject
command has a payload described by the AkCmd_RegisterGameObject
structure, while AkCommand_SetRTPC
has the payload described by the AkCmd_SetRTPC
structure. See the documentation for AkCommand
to learn which payload structures are associated with command codes.
Some commands require additional payload data of variable size. For example, the AkCommand_SetListeners
command must be followed by an array of listener IDs. The number of listeners can vary based on the needs of the game.
To add a variable-sized payload to a command, first add the command with AK_CommandBuffer_Add
, then add the variable-sized payload with the appropriate function based on the payload's type:
AK_CommandBuffer_AddString
. This function associates a name with a game object, which is useful during profiling.AK_CommandBuffer_AddArray
. This function is used for commands with a "number of items" field, such as AkCmd_SetListeners
and AkCmd_SetMultiplePositions
.AK_CommandBuffer_AddExternalSources
. This function is used exclusively for AkCommand_PostEvent
.AK_CommandBuffer_AddGeometry
. This function is used exclusively for AkCommand_SA_SetGeometry
.For example, the following code adds a AkCommand_SetListeners
command with three listener IDs:
If you do not add extra payload data to a command that requires it, the command fails with an AK_InvalidParameter
result. To learn whether a particular command requires extra payload data, refer to the documentation of the command.
To execute the commands, you must call AK_CommandBuffer_Submit()
to submit the buffer to the sound engine. This function places the buffer in the sound engine's pending message queue. Its commands are processed asynchronously on the next audio rendering frame, in the order in which they were added to the buffer.
![]() | 주의: Avoid releasing or writing to the buffer until all commands in the buffer are processed. |
When a command is processed, the result of the command is written in the command buffer itself. Clients must designate a callback function before submitting the buffer in order to inspect command results. When this callback is called by the sound engine, clients can iterate through the commands to check result codes.
You can also use the callback to determine when the buffer can be re-used to submit additional commands, or when it can be released.
The following example shows how to register the command buffer callback, submit the buffer, and check results when processing is complete:
As demonstrated above, it is customary to re-use the same buffer for multiple command submissions to avoid churn on the memory manager. However, as with all other memory resources, command buffers must eventually be released. To release a command buffer, call AK_CommandBuffer_Destroy()
.
![]() | 주의: Do not use AK_CommandBuffer_Destroy() to free a manually-allocated command buffer! Use your engine's memory allocation hooks instead. Only buffers created by AK_CommandBuffer_Create() should be released using AK_CommandBuffer_Destroy() . |
When you use the Command Buffer API to post Events, the user generates Playing IDs before the Events are posted. In contrast, the C++ AK::SoundEngine::PostEvent
API returns a valid Playing ID after the Event is posted.
To post an event with Command Buffer, first generate a Playing ID with AK_SoundEngine_GeneratePlayingID()
. Next, use this ID when you construct the AkCmd_PostEvent
command. Finally, submit the buffer that contains the commands.
The PostEvent command consumes its Playing ID when processed. Therefore, it is not possible to share the same Playing ID for multiple PostEvents. A new Playing ID must be generated for each PostEvent command. PostEvent commands that refer to Playing IDs that were previously consumed will fail to process.
Here is an example of a command buffer that posts two distinct Events:
Clients do not have to use the AK_CommandBuffer_Init()
and AK_CommandBuffer_Add()
functions to construct a command buffer. The content of the buffer can be constructed manually. Its memory layout is defined by the various structures defined in AK/command_types.h
.
The following diagram shows the sequential layout of a valid command buffer in memory.
+-----------------------------------------------------+ | CBH | CH1 | CP1 | CH2 | CP2 | ... | CHN | CPN | EOB | +-----------------------------------------------------+ CBH = Command Buffer Header (AkCommandBufferHeader) CHN = Nth Command Header (AkCommandHeader) CPN = Nth Command Payload. Its size is dictated by the command header's "size" member. EOB = End-of-buffer marker. AkCommandHeader structure with the command code AkCommand_EndOfBuffer (0) and payload size 0.
Note the following about the preceding diagram:
AK_CommandBuffer_AddExternalSources
and AK_CommandBuffer_AddGeometry
to serialize these structures to a command buffer.![]() | 주의: Submitting or iterating over a malformed command buffer can lead to undefined behavior or crashes. |
프로젝트를 등록하세요. 아무런 조건이나 의무 사항 없이 빠른 시작을 도와드리겠습니다.
Wwise를 시작해 보세요