Table of Contents

Streaming / Stream Manager

Introduction

Limited bandwidth often makes access to storage devices a bottleneck in games. Therefore, to keep data transfer requests orderly, game titles usually centralize access to I/O. This order is based on relative priority and consumer requirements relative to transfer size, throughput and latency. Audio is typically I/O intensive: music and long sounds are usually streamed from disk as they are played back.

Audiokinetic's I/O Streaming Solution

Audiokinetic Sound Engine's I/O streaming solution consists of an autonomous, overridable streaming management module. The following figure is a block diagram representing the module and its place in the sound engine / game architecture:

Streaming_WithCustomLowLevelIO.gif

Its public interface, defined in IAkStreamMgr.h, is intended to be used by both the sound engine and the game. The former uses the interface to load SoundBanks and stream audio files. The latter may use it to load graphics, textures, levels, saved games, and so on.

The public interface is a platform-independent high-level abstraction for data transfers involving storage (I/O) devices that wraps handles to files or other objects close to the platform's operating system or hardware into so-called "streams". In this documentation, the module that implements the stream objects and stream factory is referred to as the High-Level Stream Manager, or simply the Stream Manager.

You may override the Stream Manager entirely if you wish, but the Wwise SDK comes with a default implementation. This default implementation defines another level for you to hook your I/O-related code, called the Low-Level I/O, which is much simpler to use. It is the preferred way of integrating Wwise I/O into your game.

Default Streaming Manager Information

Note.gif
Note: Throughout this chapter, you will encounter boxes like this that give additional details specific to Audiokinetic's implementation of the Stream Manager.

Functions and structures related to streaming but that are specific to the default implementation of the Stream Manager, such as AK::StreamMgr::Create(), are defined in AkStreamMgrModule.h, in the SDK's include directory.

Integrating Wwise I/O

Quick Integration

To get things up and running quickly when you first integrate Wwise, use the default Stream Manager and the low-level I/O samples that ship with the Wwise SDK:

1) Link with AkStreamMgr.lib.

2) Include the default File Location Resolver and Blocking I/O Hook into your game's project:

  • SDK/Samples/SoundEngine/{Platform name}/AkDefaultIOHookBlocking.h and .cpp
  • SDK/Samples/SoundEngine/{Platform name}/AkFileHelpers.h
  • All the files in SDK/Samples/SoundEngine/Common/

3) After creating the Stream Manager, instantiate and initialize the low-level I/O hook device CAkDefaultIOHookBlocking. Note that you may use CAkFilePackageLowLevelIOBlocking instead, which implements the File Package extension of the I/O hook (see next section). It will be ready if you eventually need it. Refer to Initializing the Streaming Manager for an example of how to initialize it.

4) The default file location resolver (implemented in CAkFileLocationBase) needs to be told the directory where files generated by the Wwise authoring tool are located. In your code, set the base path where audio assets are deployed, using CAkDefaultIOHookBlocking::SetBasePath() (or CAkDefaultIOHookBlocking::AddBasePath() ). If you have localized assets, set the current language on the default Stream Manager module using AK::StreamMgr::SetCurrentLanguage(). The default file location resolver concatenates the language name to the base path to find localized assets.

Warning.gif
Warning: Do not append a directory separator (slash or backslash) to the language name that you pass to AK::StreamMgr::SetCurrentLanguage().

The sound engine is now ready to load soundbanks and play streamed files from the directory you specified in SetBasePath()(or AddBasePath() ). Note that in order to automatically copy stream files in the soundbanks output directory in the Wwise tool, you should use the "CopyStreamedFiles" executable as a post-soundbank-generation step. Refer to the SoundBank Settings of the Wwise Help for more details.

File Packages

If you instantiated the CAkFilePackageLowLevelIOBlocking device, you are a few steps away from being ready to also use file packages. A file package (*.PCK) is a single file resulting from the concatenation of all soundbanks and streaming audio files from a Wwise project. You may also assign soundbanks and streaming files to different file packages. Refer to the File Packager utility documentation for more details.

1) Have the Wwise tool automatically generate a file package with your soundbanks and streaming files after soundbank generation, using the "FilePackager" executable as a post-soundbank-generation step (see the SoundBank Settings section of the Wwise Help).

2) In your code, load the file package(s) explicitly using CAkFilePackageLowLevelIOBlocking::LoadFilePackage(). LoadFilePackage() opens the file package from the path you specified in SetBasePath()(or AddBasePath() ). In the deployement directory of audio assets, you need to include your file packages, but not the soundbanks and streamed files that they contain. When you load a file package, its header is parsed and a look-up table is created inside CAkFilePackageLowLevelIOBlocking. When the sound engine tries to open a file, following a call to AK::SoundEngine::LoadBank() or an event involving playback of a streamed file, CAkFilePackageLowLevelIOBlocking searches for it in the look-up tables of all its loaded file packages. If it is not found, the file is searched in the base path.

Routing I/O Reads to Your Own I/O Manager

CAkDefaultIOHookBlocking reads files using the platform file system API. If your game engine already has an I/O manager, you might want to route the I/O read request issued from the Wwise Stream Manager to your I/O manager instead. Edit CAkDefaultIOHookBlocking::Read() to call your I/O manager instead of the platform file system. If necessary, you can also edit CAkDefaultIOHookBlocking::Open().

Going Further: Working with the Low-Level I/O

The default Stream Manager implementation provided in the SDK sits over a submodule called the Low-Level I/O. The classes described above are all provided in the Wwise SDK as sample implementations of the Low-Level I/O. Their associated files are listed here: Default Low-Level I/O Implementation.

The preferred way of integrating Wwise I/O into your game engine is to let you implement a Low-Level I/O layer as an adapter between Wwise I/O and your I/O management technology. Typical implementations of the Low-Level I/O in games range from very simple to very complex and highly customized. You may use the samples as a starting point.

The Low-Level I/O module has 2 purposes:

  • Resolves files location on disk: Files generated by Wwise can be placed anywhere on the game disk, but code must be written to ensure proper mapping between SoundBank and streaming file names and IDs to file descriptors used by the platform's file system.
  • Abstracts all low-level I/O operations: All I/O transfer requests (read/write) scheduled by the Stream Manager are delivered there.

Wwise I/O Performance

The initialization settings of the Stream Manager have an impact on how it interacts with your Low-Level I/O system, and on overall I/O performance. They are described thoroughly in chapter Audiokinetic Stream Manager Initialization Settings. Chapter I/O Tips, Troubleshooting and Optimization may help you tweak them.

High-Level Stream Manager

The Stream Manager, whose interface is defined in IAkStreamMgr.h, is used by the Wwise sound engine to read soundbanks and streamed audio files. You are also welcome to use it for all your game I/O if you don't already have an I/O manager. Likewise, if you write a custom source plug-in, you may access the Stream Manager.

Section High-Level Stream Manager API Description explains its API in details. You may skip this chapter if you don't use it directly as a client, and only integrate Wwise I/O into your game by implementing the low-level I/O hooks.

Here are just a few basic concepts. The Stream Manager manages abstract streams of data of two different types: standard streams and automatic streams.

The Stream Manager is intended to be thread-safe, but only one thread may own a given stream.

The main interface AK::IAkStreamMgr is accessible from anywhere by calling AK::IAkStreamMgr::Get(). From there, you may create and use stream objects.

Further Information

The following sections provide more detailed information about streaming: