Skip to content

Concepts

Streams, pins and wires

Every audio object is a box with pins. A stream leaves a box on an output pin, travels down a Wire, and enters another box on an input pin. Nothing makes sound until a chain ends in something that renders it, usually an AudioDeviceOutput (the player's speakers).

flowchart LR
  P[AudioPlayer] -- Wire --> EQ[AudioEqualizer] -- Wire --> O[AudioDeviceOutput]

Wire properties:

Property Meaning Default
SourceInstance The box the stream comes from —
SourceName Output pin on the source "Output"
TargetInstance The box the stream goes into —
TargetName Input pin on the target "Input"
Connected Read-only. True only when both ends and both pins exist and the wire would not create a cycle —

You only change pin names for the few objects with extra pins: the Sidechain pin on AudioCompressor, and the per-channel pins on AudioChannelMixer / AudioChannelSplitter.

The Wire instance can live anywhere. Its parent does not matter, only its two ends. Most people parent it to one end so it is destroyed along with that end.

Fan-in and fan-out

  • Fan-in. Several wires into one input pin are summed. That makes any effect a bus: wire ten players into one AudioReverb instead of making ten reverbs.
  • Fan-out. One output pin can feed many wires. Each target gets its own copy of the stream. One AudioPlayer can drive two speakers, or an emitter and an analyzer at once.
  • Order matters. Chorus then distortion sounds different from distortion then chorus.
  • No cycles. A wire that would close a loop reports Connected = false and carries nothing.

Methods every wirable object shares

Member What it does
GetInputPins() / GetOutputPins() List the pin names
GetConnectedWires(pin) The wires on a pin, which is useful for rewiring at runtime
WiringChanged(connected, pin, wire, instance) Fires when a wire attaches to or detaches from a pin

Effects also have Bypass. When it is true the stream passes through untouched. Use it to switch an effect in and out without rewiring.

2D and 3D audio

2D (non-spatial). The stream goes straight to the speakers, at the same volume wherever the player is. It suits UI, music and in-ear radio.

flowchart LR
  P[AudioPlayer] --> O[AudioDeviceOutput]

3D (spatial). The stream is broadcast into the world by an AudioEmitter (a virtual speaker). An AudioListener (a virtual microphone) picks it up, spatialized and attenuated by distance and angle. The listener's output goes to the speakers.

flowchart LR
  P[AudioPlayer] --> E[AudioEmitter<br/>on a Part]
  E -. through the 3D world .-> L[AudioListener<br/>on the Camera]
  L --> O[AudioDeviceOutput]

Emitters and listeners take their position from their parent, which must be an Attachment, Camera or PVInstance (a Part or Model). Under anything else they are silent. Alternatively, set PositionType = Instance and point PositionInstance at something.

Where the listener comes from

SoundService.DefaultListenerLocation (labelled ListenerLocation in Studio) decides whether Roblox makes the listener for you:

Value Result
Default A listener under Workspace.CurrentCamera, but only in experiences with voice enabled
Camera A listener under the camera, plus an AudioDeviceOutput in SoundService, wired together
Character A listener at your character, facing where your camera faces, plus the output
None Nothing. Make your own in a LocalScript

You can have more than one listener. Each is a separate microphone in the world, and each needs its own wire to an output (or somewhere else) before it does anything.

Interaction groups

AudioEmitter.AudioInteractionGroup and AudioListener.AudioInteractionGroup are strings. A listener only hears emitters with the same group. The default is the empty string, so out of the box every listener hears every emitter.

Use groups to build separate acoustic worlds in the same space. For example, emitters in a "Radio" group are heard only by a "Radio" listener, never by the normal camera listener.

Attenuation

How loud an emitter is at a listener is the product of four curves:

  • Emitter distance. Pick a preset with DistanceAttenuationMode (Inverse, InverseTapered, Linear, LinearSquared) between DistanceAttenuationBounds (default 4 to 10,000 studs), or use Custom with SetDistanceAttenuation({ [studs] = volume }). An empty custom curve means inverse-square.
  • Emitter angle. Set it with SetAngleAttenuation({ [degrees 0–180] = volume }) to make a sound directional. The default is flat.
  • Listener distance. AudioListener:SetDistanceAttenuation gives one listener better or worse hearing. The default is flat.
  • Listener angle. AudioListener:SetAngleAttenuation works the same way.

Curves are linear between points and flat beyond the ends, with up to 400 points each. emitter:GetAudibilityFor(listener) returns the combined 0–1 result, which you can use in game logic ("can the monster hear you?").

Acoustic simulation

When it is on, Roblox automatically muffles sound through walls (occlusion), bends it around corners (diffraction) and adds room reverb from the real geometry. It needs all three switches:

  • SoundService.AcousticSimulationEnabled = true (off by default)
  • AudioEmitter.AcousticSimulationEnabled = true (on by default)
  • AudioListener.AcousticSimulationEnabled = true (on by default)

Parts take part through BasePart.AudioCanCollide. Materials take part through PhysicalProperties.AcousticAbsorption (more absorption means fewer echoes) and Density (denser means more muffling). Fine-grained switches OcclusionEnabled, DiffractionEnabled and ReverbEnabled exist on emitters and listeners (Enum.SimulationMode). Simulation quality scales with the player's graphics quality and may turn itself off to hold frame rate.

Voice is just another source

With VoiceChatService.UseAudioApi = Enabled, every voice-eligible player gets an AudioDeviceInput (their microphone, as a stream). The default setup wires it to an AudioEmitter on their character, and the camera listener hears it. That is ordinary proximity chat built from the same objects, so you can re-route, filter or analyze it like any other stream. See Voice chat.

flowchart LR
  M[AudioDeviceInput<br/>under Player] --> E[AudioEmitter<br/>in Character]
  E -. 3D .-> L[AudioListener<br/>on Camera] --> O[AudioDeviceOutput]

Every client renders its own graph

Audio is mixed only on clients. The server never makes sound. Instances the server creates replicate, so everyone builds the same graph. A LocalScript can also add its own wires and effects that only that player hears. Per-player mixes, such as an in-ear radio, a muffled underwater filter or a deafened state, come from this. See Client, server and limits.