Table of Contents

Integrating Secondary Outputs

In Wwise, a secondary output designates any physical audio end-point that is not the regular TV audio output. The most common secondary outputs are the game controller speakers and headsets. The Secondary Output feature allows you to define a separate mix for each of these outputs, leaving the main speaker/TV mix unaffected. The same Wwise feature set applies to the secondary outputs as for the regular mix, without any particular restrictions except that the output targets controllers instead of the speaker/TV.

Bus Routing

On the authoring side, you need to create new master busses to be able to define a different mix for an Audio Device. Then change the Audio Device ShareSet property on that new bus to point to a different device. Note that if you want to use an Audio Device plug-in created by a third party, you might need to create an Audio Device ShareSet of the right plug-in type first. Then the sounds can be routed normally to the new bus or any child bus. See Audio Devices for information on which Audio Device is available with Wwise.

Setting the Output Bus directly is the preferred method for sounds that are normally tied to only one secondary output instance. For example, player-initiated gunshots, tennis racket whacks, PDA sounds, gameplay feedback, and so on. However, you can use a User or Game Send to an Auxiliary Bus inside any other bus hierarchy. This is the preferred method if the same sound is going to be heard in multiple outputs and the TV at the same time, such as with a spy camera or announcements.

It is possible to play the same sound on multiple controllers and on TV at the same time, using the same source. On the design side, there is no knowledge of how many players might be playing the game. The bus hierarchy will be used as a template for routing for each output registered from the game. So, each output may have a different mix and Effect applied, depending on the sources played, as well as RTPC and Switch values active on the game objects. See an example of this in the Examples section below.

A note on synchronization of outputs

When outputting the same audio on many devices, such as the TV and a game controller, you will probably notice latency between the devices. This is unavoidable due to different hardware in the audio signal's path. On the controller side, the signal may have to travel through a wireless channel, which might give a different delay than for wired controllers. For the TV, once the signal is out of the console, it goes through a receiver and/or a TV, whose processors add a certain amount of delay. Since the delay produced by the AV setup is different for each system, it's not possible to synchronize sounds routed simultaneously to the speaker/TV and the game controllers. Your sound design may need to take this constraint into consideration.

Setting up devices, listeners and game objects for multiple outputs

In the case of multiple outputs of the same type (think, for example, a game controller speaker), it is necessary to discriminate between each instance of the devices. The regular Listener/GameObject concept is used because it also allows specific listener/emitter routing. See Concept: Listeners for more information. It is the responsibility of the game programmer to associate the output device with a Listener using AK::SoundEngine::AddOutput. The programmer must set the association between the listeners and game objects using AK::SoundEngine::SetActiveListeners. Don't forget, you can specify multiple listeners if multiple devices should play this sound at the same time (see example below).

Note.gif
Note: It is not necessary to have multiple listeners if there is only one output of a particular type (such as System, DVR). In this case, Wwise can rely on the routing specified in the Wwise project. This is also true for player-specific outputs (such as Game Controller Speaker and Communication) if the game is single-player. In other words, if there will only be one controller active in the game. Read more about listeners in Integrating Listeners.
Note.gif
Note: In the case of player-devices, the game code is responsible for calling AK::SoundEngine::AddOutput and AK::SoundEngine::RemoveOutput whenever a game controller is connected or disconnected from the system. Wwise can't know automatically which device to associated to which listener and, conceptually, which player. System devices (such as main output and DVR) are handled automatically by Wwise.

Examples

These examples are written for the PS4, but can apply to all other platforms. Please check the documentation for the function AK::SoundEngine::AddOutput. You can find a working example of multiple output management in the Integration Demo Sample, in the DemoMotion page (multi-player), and in the BGMDemo page (DVR/BGM management).

Note.gif
Note: These examples omitted the required AK::SoundEngine before the function calls, just to make it easier to read.

Code to get the UserIDs (PS4 only):

SceUserServiceLoginUserIdList list;
sceUserServiceGetLoginUserIdList(&list);

Sound on one game controller output:

// Add a secondary output connected to the speaker endpoint for player 0.
AkOutputSettings outputSettings("Game Controller Speaker", list.userId[0] /*Player ID (first player)*/);
AddOutput(outputSettings);

// Play an Event. In the Wwise project, this sound must be routed to a master bus that is set to output in "Game Controller Speaker" (or any sub-bus).
PostEvent("Play_Pow", MY_GAME_OBJECT);

Same sound on two different controllers:

// Add a secondary output connected to the speaker output for player 0, associated with listener #1.
AkOutputSettings outputSettings1("Game Controller Speaker", list.userId[0] /*Player ID (first player)*/);
AddOutput(outputSettings1, NULL, listenerArray1, 1);

// Add a secondary output connected to the speaker output for player 1, associated with listener #2.
AkOutputSettings outputSettings2("Game Controller Speaker", list.userId[1] /*Player ID (first player)*/);
AddOutput(outputSettings2, NULL, listenerArray2, 1);

// Set a game object to emit sound to the listener 1(player 0) and 2 (player 1).
SetActiveListeners(EXISTING_GAME_OBJECT, listenerArrayBoth, 2);

// Play an Event. In the Wwise project, this sound must be routed to a master bus that is set to output in "Game Controller Speaker" (or any sub-bus).
PostEvent("Play_Pow", EXISTING_GAME_OBJECT);

Different sounds on two different controllers:

// Add a secondary output connected to the speaker output for player 0, associated with listener #1.
AkOutputSettings outputSettings1("Game Controller Speaker", list.userId[0] /*Player ID (first player)*/);
AddOutput(outputSettings1, NULL, listenerArray1, 1);
AkOutputSettings outputSettings2("Game Controller Speaker", list.userId[1] /*Player ID (first player)*/);
AddOutput(outputSettings2, NULL, listenerArray2, 1);

// Set a game object to emit sound to the proper listeners.
RegisterGameObj(MY_GAME_OBJECT1, listenerArray1, 1);    
SetActiveListeners(MY_GAME_OBJECT1, listenerArray1, 1);
RegisterGameObj(MY_GAME_OBJECT2, listenerArray2, 1);    
SetActiveListeners(MY_GAME_OBJECT2, listenerArray2, 1);

// Play an Event. In the Wwise project, this sound must be routed to a master bus which is set to output in "Game Controller Speaker" (or any sub-bus).
PostEvent("Play_Pow", MY_GAME_OBJECT1);
PostEvent("Play_Pif", MY_GAME_OBJECT2);

Same sound on one game controller output and on the TV:

// Add a secondary output connected to the speaker output for player 0, associated with listener #1.
AkOutputSettings outputSettings1("Game Controller Speaker", list.userId[0] /*Player ID (first player)*/);
AddOutput(outputSettings1, NULL, listenerArray1, 1);

// Set a game object to emit sound to the listener 0 (TV) and 1 (controller for player 0).
AkGameObjectID [] listenerArrayWithDefault = {MY_MAIN_LISTENER, MY_LISTENER1};  // MY_MAIN_LISTENER is the listener you normally use, defined by AK::SoundEngine::SetDefaultListeners.
RegisterGameObj(MY_GAME_OBJECT);
SetActiveListeners(MY_GAME_OBJECT, listenerArrayWithDefault, 2);

// Play an Event.  
// In the Wwise project, this sound must be routed to a master bus that is set to output in "Game Controller Speaker" (or any sub-bus).
// Also, this sound must have an Auxiliary send routed to the master Audio Bus.
PostEvent("Play_Pow", MY_GAME_OBJECT);

Here's an example of adding a secondary output on Windows, namely the headphones:

Note.gif
Note: On Windows, all devices are "System" devices. Therefore, adding a device means it is necessary to discriminate between them (see Setting up devices, listeners and game objects for multiple outputs for information). Consequently, we need a different listener.
// Will search for a device that has "Headphones" in its name.
uDeviceID = AK::GetDeviceIDFromName("Headphones");  

// Add a secondary output connected to the device found previously, associated with listener1.
AkOutputSettings outputSettings1("System", uDeviceID);
AddOutput(uoutputSettings1, NULL, listenerArray1, 1);

// Register a game object associated only with listener1.
RegisterGameObj(MY_GAME_OBJECT, listenerArray1, 1);

// Play an Event. In the Wwise project, this sound must be routed to a master bus that is set to output in "System" (or any sub-bus).
PostEvent("Play_Pow", MY_GAME_OBJECT);
See also: