Audio Override System - vrctxl/VideoTXL GitHub Wiki

The Audio Override System is a way of changing avatar voice/audio levels based on a system of defined zones.

First, a quick recap of how voice/audio overrides work in VRChat: for a given local player X, you can change how loud or soft other players are perceived by updating the voice/audio levels of those other players. This is local to player X. There isn't a single value to update to, for example, make a player broadcast their voice to all other players in a world. To do that, then for every player in the world, a script must locally update the level of player X so they would be heard everywhere.

The Audio Override System uses a zone and profile system to allow thinking about audio relationships at a high level and takes care of the logistics of managing all the player audio for each local player.

Components

The Audio Override System is composed of the following key components:

AudioOverrideManager

The main management object. There should only be one of these in the world. The management object is configured by specifying a default zone and listing all other zones in the system. Note that if you have zones that physically overlap, the order of the zones in this list also specifies their precedence, and earlier-listed zones will take precedence.

AudioOverrideZone

Defines a physical area and how audio is perceived by players located in that area. Audio profiles can be optionally assigned to:

  • Local Zone (how do I hear other players in the same zone as me)
  • Linked Zones (how do I hear other players standing in some other defined zone)
  • Default (how do I hear other players not in my zone or a linked zone)

The default setting also applies to the local zone if the local zone setting is not enabled. If the default setting is not enabled, it will fall through to the audio system manager's default.

Zones also get configured with a couple extra components:

  • Membership (a ZoneMembership component keeping track of players in the area)
  • Zone (A CompoundZoneTrigger component for when players enter or leave the area)

Both of these components can be defined on the same object for convenience, along with the collider that triggers the compound trigger.

AudioOverrideSettings

Defines a reusable audio profile with the specific settings for avatar voice and audio. TXL provides a few common profiles by default like Default, Broadcast, and Mute.

AudioPlayerOverrideList

Allows overriding how a player is perceived in one or more zones, regardless of where they are physically. This component is particularly useful in supporting setups like mobile microphones. As a convenience, the component can bind automatically to a TXL PickupTrigger to support this.

Zone Relationships

Zone Diagram

The above image shows a generalized view of players in a world with multiple zones defined. Focusing on the red local player X, a profile is going to be assigned to every other player in the world affecting how X perceives them. Most of these assignments will come from the configuration of Zone A, which is where X is currently standing.

The other players in the same zone (purple) will be assigned Zone A's local settings profile.

There are two other zones linked to A: Zones B and C. The Zone A configuration lists a profile to use for each of those. So players standing in Zone B will be assigned the profile in A's linked zones list that's associated with B. And players in Zone C will be assigned the profile associated with C. Note that players in C are also technically in B as well, but C takes precedence because of how zones were ordered in the manager.

There's some players standing in Zone D, but because D is not in A's list, these players are considered the same as "default" (players not standing in any zone at all), and all of them will get assigned A's default settings profile.

All of this is from Player X's perspective, and this process is repeated locally for each player in the world. Take the single player standing in Zone D for example (we'll call them Player Y). If there's no zones linked in D's configuration, then every other player is "default" from Y's perspective and will have Zone D's default profile assigned to them.

Default Zone

The default zone is a special use of the zone component, and it should be configured with no membership or trigger components, and no local zone profile. The linked zones list SHOULD be filled out for the default zone, as this determines how "anyone else in the world" hears players in other zones, if more specific rules don't apply.

The default settings profile should be specified, and this is what is applied when no other rules match at all. This should commonly be the default profile, but other settings can be useful in some cases like the mute profile.

Example: Simple Stage

Let's examine a simple setup: a single zone that defines a stage. Any player standing on the stage should broadcast their voice to all players in the world that are not on the stage. The audience should continue to be able to talk among themselves normally, and performers on the stage should hear everyone else normally (including other performers on the stage).

Zone Diagram

The above diagram shows the two points of view being considered.

For stage performers, other players in the zone (purple) should be assigned the default profile. And anyone else in the world should also be assigned the default profile. This meets the requirement that performers should hear anyone normally.

For audience members, players in Zone A (blue) should be assigned the broadcast profile, so they can be heard loudly no matter how far away they are. Anyone else in the world should be assigned the default profile.

This configuration requires two zones: Stage Zone (Zone A in the diagram) and Default Zone.

Profile assignments for Stage Zone end up being:

  • Local Settings: Enabled, Default
  • No linked zones configured
  • Default Settings: Enabled, Default

Stage Zone Config

Profile assignments for Default Zone end up being:

  • Local Settings: Not enabled
  • Linked Zones:
    • Stage Zone Settings: Broadcast
  • Default Settings: Default

Default Zone Config

The manager has a single linked zone.

Manager Config

Example: Simple Microphone

What about a player being able to carry a microphone around the world to broadcast their voice? In this case, there are no logical zones to define at all.

It's possible to setup the system with only the Default Zone, and then utilize an AudioPlayerOverrideList to override how the player with the microphone is perceived by players in the default zone (e.g. anywhere in the world).

The default zone would be configured with no linked zones and just the default profile to use. A separate AudioPlayerOverrideList object would contain the default zone in its list of zones, with the broadcast profile associated.

Now any player that gets added to the override list will broadcast to the world. This can be done programmatically using the API, but for convenience a PickupTrigger can be assigned to the list to automate adding/removing the player holding a specific object. The PickupTrigger component itself can be configured to utilize trigger hold or reference an ACL.

Default Zone and Manager Config

(Note the manager and default zone are specified on the same object in this example)

Override Config

API

AudioOverrideSettings

_Apply (VRCPlayerAPI player)

Apply all of the voice and avatar audio settings to the specified player (this is local)

AudioOverrideZone

_SetLocalActive (bool state)

Enables or disables the associated local settings profile for this zone.

_GetLocalSettings ()

Gets the AudioOverrideSettings profile object used for local settings.

_SetLocalSettings (AudioOverrideSettings profile)

Updates the AudioOverrideSettings profile object used for local settings.

_SetDefaultActive (bool state)

Enables or disables the associated default settings profile for this zone.

_GetDefaultSettings ()

Gets the AudioOverrideSettings profile object used for default settings.

_SetDefaultSettings (AudioOverrideSettings profile)

Updates the AudoOverrideSettings profile object used for default settings.

_GetLinkedZoneActive (AudioOverrideZone zone)

Returns whether the linked zone is active. Also returns false if the zone is not linked.

_SetLinkedZoneActive (AudioOverrideZone zone, bool state)

Enables or disables whether the linked zone is active. Only applies to zone objects that were linked.

_GetLinkedZoneSettings (AudioOverrideZone zone)

Gets the AudioOverrideSettings profile object associated with the linked zone.

_SetLinkedZoneSettings (AudioOverrideZone zone, AudioOverrideSettings profile)

Updates the AudioOverrideSettings profile object associated with the linked zone.

_ContainsPlayer (VRCPlayerApi player)

Asks the attached membership object if the player is tracked in that list

_Apply (VRCPlayerApi player)

Applies a settings profile to the given player, based on the rules defined in the zone. Returns false if no rules applied, and thus no voice updates were made.

_AddPlayerOverride (VRCPlayerApi player, AudioOverrideSettings settings)

Creates an override where the given player will be perceived with the given settings for anyone in the zone, and then applies the audio updates.

_RemovePlayerOverride (VRCPlayerApi player)

Removes a previously created override, and then applies audio updates.

_GetPlayerOverride (VRCPlayerApi player)

Gets the associated AudioOverrideSettings profile object is an override has been set for the given player.

AudioOverrideManager

_RebuildLocal ()

Updates/applies voice and audio settings to all players in the world, from the local player's point of view.

_FindActiveZone (VRCPlayerApi player)

Gets the AudioOverrideZone object that the player is active in, or null if they aren't in any. If player is in multiple zones, only the first is returned.

AudioOverrideList

_Pickup ()

A convenience method that binds the local player, causing their override to be registered with the list's associated zones. Used by PickupTrigger automatically.

_Drop ()

The analogue to _Pickup, and causes the local player to be removed from any associated zone overrides.

_AddPlayer (VRCPlayerApi player)

Registers an override for the given player in all of the list's associated zones.

_RemovePlayer (VRCPlayerApi player)

Removes the override for the given player from all of the list's associated zones.