Audiokinetic Stream Manager Initialization Settings

Default Streaming Manager Information

This chapter is specific to the default implementation of the high-level Stream Manager's API.

The initialization settings of the Stream Manager and the AK::StreamMgr::Create() method are specific to Audiokinetic's implementation, and are defined in AkStreamMgrModule.h.

Here is a description of the initialization settings of the default implementation of the Stream Manager. You will certainly have to tweak these settings for your game at some point in order to make best use of I/O and memory resources.

Stream Manager Settings

The AkStreamMgrSettings structure defines the settings needed for the entire Stream Manager. Default values indicated in each subsection are the values returned by AK::StreamMgr::GetDefaultSettings(). These default values may not be adequate for your system. The information contained in I/O Tips, Troubleshooting and Optimization may help you choose optimal values.

Memory Size

AkStreamMgrSettings::uMemorySize specifies the size of the memory pool that the Stream Manager will create for itself and all its small objects: streaming devices, stream objects, pending transfer objects, references to stream buffers, profiler stream names, deferred file open commands, and so on. That is, everything except the I/O memory for automatic streams, whose pool is specific to each streaming device (specified by AkDeviceSettings::uIOMemorySize). It should be the smallest value possible, but large enough so that it does not restrict the number of streams that can be played. You may use the Memory tab in Wwise’s Advanced Profiler view to evaluate small streaming object memory usage (in the Stream Manager pool).

Most of the memory required from this pool is allocated when streaming devices are created. Run-time allocations essentially consist of the stream objects themselves, their profiling names (in DEBUG and PROFILE configurations only), and temporary structures needed to handle deferred file opening (see Deferred Opening) if applicable.

Default: 64 KB.

Streaming Devices Settings

The AkDeviceSettings structure defines the settings needed for each device, created with AK::CreateDevice().Default values indicated in each subsection are the values returned by AK::StreamMgr::GetDefaultDeviceSettings(). These default values may not be adequate for your system.

I/O Memory Size

AkDeviceSettings::uIOMemorySize is the total size of the memory reserved for a device’s automatic streaming. The device creates a special memory pool, to which automatic stream I/O data is written. If you don’t plan to use any automatic streams, specify zero. Note, however, that the sound engine uses automatic streams to play streamed audio files. AkDeviceSettings::pIOMemory, AkDeviceSettings::uIOMemoryAlignment and AkDeviceSettings::ePoolAttributes are additional parameters that are passed directly to the pool creation method, AK::MemoryMgr::CreatePool().



Granularity is specified by AkDeviceSettings::uGranularity. It defines the standard request size sent to the Low-Level I/O, whether it is sent from a standard stream (sliced operation) or an automatic stream (size of a single stream buffer). Automatic streams use a variable number of buffers, depending on the memory available. The total number of buffers available for automatic streaming is equal to
AkDeviceSettings::uIOMemorySize / AkDeviceSettings::uGranularity.

Tip: To avoid starvation because of memory, streams should be at least double-buffered. Therefore, the I/O memory size should be set to at least
2 * uGranularity * nominal_number_of_streams
Note that the actual number of buffers required per stream is dynamic and depends on stream heuristics and the devices target buffer length (see AkDeviceSettings::fTargetAutoStmBufferLength). The proper way to determine the I/O memory size that is required for your needs is to compute the sum of the throughput required by all your streams in your worst case scenario and multiply it by fTargetAutoStmBufferLength. In practice, it is easier to start with a large value, profile your game with the Wwise profiler, and use the peak value reported for I/O usage in the Streaming Devices tab.

Default: 16 KB

Scheduler Type

The type of streaming device scheduler depends on AkDeviceSettings::uSchedulerTypeFlags. It determines the handshaking mode with the Low-Level I/O. Streaming devices created with AK_SCHEDULER_BLOCKING flag work with AK::StreamMgr::IAkIOHookBlocking, using synchronous handshaking. Streaming devices created with the AK_SCHEDULER_DEFERRED_LINED_UP flag work with AK::StreamMgr::IAkIOHookDeferred, using asynchronous handshaking. Refer to High-Level Devices Specificity for a discussion on high-level device schedulers.

Caution: Using a deferred I/O hook with an AK_SCHEDULER_BLOCKING device and vice-versa results in a run-time crash.


I/O Thread Properties

All high-level devices use a separate thread to post transfer requests to the Low-Level I/O called "AK::IOThread". You can specify properties for this thread by using AkDeviceSettings::threadProperties. AkThreadProperties is defined for each platform in SDK/include/AK/Tools/{Platform name}/AkPlatformFuncs.h. This method typically specifies thread priority and processor.

Tip: The I/O scheduler thread should have a priority above normal because it does not use much of the CPU: it spends most of its time waiting for streams to service, or waiting for the disk controller. However, when it needs to choose a task and post it to the Low-Level I/O, it should be able to do so quickly to maximize the storage device throughput.

Default: Default platform-specific thread properties (as returned by AKPLATFORM::AkGetDefaultThreadProperties()), with a priority equal to AK_THREAD_PRIORITY_ABOVE_NORMAL (defined in AkPlatformFuncs.h).

Target Buffering Length

AkDeviceSettings::fTargetAutoStmBufferLength is a heuristic for a device’s I/O scheduler. It applies to automatic streams only. It specifies the ideal buffering time that should be reached, per stream, in milliseconds. The Stream Manager performs I/O for a given stream until that buffering length is met. The time value translates into buffer size using the stream’s throughput heuristic. For example, a 16-bit stereo sound sampled at 44.1 KHz requires a throughput of 172.3 Kb/s. If the target buffer length is set to 380 ms, the target buffer size for this stream will be about 64 Kb. With more buffering, streams are less likely to starve. On the other hand, the I/O scheduler will be busier and use more CPU, and a larger amount of memory in the streaming I/O pool. The optimal value depends mainly on the low-level storage device bandwidth and the amount of memory available for streaming. Fast devices should use a smaller buffering length, whereas slower devices, or devices whose throughput has a large standard deviation (due to seeking, for example) should use a larger value. When all automatic streams reach their target buffering length, and there is no pending standard streaming operation, the I/O scheduler becomes idle.

Tip: The ideal target buffering length is proportional to the time at which your low-level device transfers data. Try to specify the lowest value possible without having source starvation notifications appear in the Wwise Profiler, under reasonable conditions, with a sufficiently large I/O memory size. Once this is done, you may reduce the I/O memory size to the peak usage value.

Default: 380 ms.

Maximum Number of Concurrent I/O Transfers

AkDeviceSettings::uMaxConcurrentIO concerns asynchronous low-level devices only (AK_SCHEDULER_DEFERRED_LINED_UP scheduler flag). It is the maximum amount of low-level I/O transfers that the streaming device may post concurrently to the low-level I/O at any given time. When the limit is reached, the I/O thread will stop posting requests to the low-level I/O even if there are streams buffered below their target. You may use this value to safely allocate static arrays of structures that you need to track each pending transfer.


Tip: If you specify 1, you get the same behavior as with a synchronous device (AK_SCHEDULER_BLOCKING scheduler flag), with asynchronous handshaking instead. This can be useful if your I/O manager only exposes an asynchronous API.

You may be tempted to use a large value for this parameter, but there are downsides to this. The streaming device's scheduler posts low-level requests according to the state of each stream at the time it inspects them. If you let it send a lot of requests, and let them remain in the low-level I/O for a long time, the situation is more likely to change in the meantime. For example, streaming sounds may stop, or stop looping. In such cases, these transfers are cancelled and I/O data is flushed upon reception. This may result in a lot of wasted bandwidth.

Large amounts of concurrent requests should only be used with devices whose throughput is not linear with the amount of requests. For example, some DMA controllers can be programmed to process many transfers, but the moment when they complete is mostly independent of the amount of transfers that were programmed.

Default: 8 (ignored by AK_SCHEDULER_BLOCKING schedulers).

Maximum Cache Ratio

AkDeviceSettings::fMaxCacheRatio determines whether data caching is enabled or not: with values greater than 1, caching is enabled.

Streaming devices support data caching into their streaming pool. When an I/O operation is executed for a memory block, file metadata is attached to it. If the same stream or another instance of the same stream requires a block of data corresponding to the same file at more or less the same position, this block of data will be used directly, thus avoiding a transfer from the low-level I/O.

You must know that critical data structures are preallocated (from the Stream Manager memory pool) when devices are created, because running out of memory at run-time would result in the I/O thread spinning over nothing with a high priority, having disastrous consequences on the game's performances.

With stream data caching, there may be more than one reference for a given memory block. References to memory blocks are an example of such preallocated critical data structures.

AkDeviceSettings::fMaxCacheRatio specifies how much references there are compared to the number of memory blocks. When AkDeviceSettings::fMaxCacheRatio is 1, there is exactly one reference per memory block, thus data caching cannot occur. If you consider that caching is not needed for a given device, you should leave AkDeviceSettings::fMaxCacheRatio to 1, as data look-up is skipped completely with this setting.

If you set AkDeviceSettings::fMaxCacheRatio to 2, there will be twice as much references as there are memory blocks, and caching will occur. The streaming device will have a slightly larger memory footprint in the Stream Manager pool when you create it with this setting. In order to determine whether this cache ratio is sufficient for your needs, profile your game using the Wwise Profiler. In the Streaming Devices tab of the Profiler, the value in the column Caching Available indicates how much of these extra references are left. When it reaches 0, no more caching can occur because the device has to respect the amount of preallocated references. At this point, even if valid data exists in the streaming cache, a new streaming buffer is refilled from the low-level I/O. So if you notice that the Caching Available often decreases close to 0 during your profiling sessions, you should consider increasing AkDeviceSettings::fMaxCacheRatio above 2 in order to optimize your usage of the data caching feature.

Default: 1 (caching disabled).