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
AudioReverbinstead of making ten reverbs. - Fan-out. One output pin can feed many wires. Each target gets its own copy of the stream. One
AudioPlayercan 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 = falseand 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) betweenDistanceAttenuationBounds(default 4 to 10,000 studs), or useCustomwithSetDistanceAttenuation({ [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:SetDistanceAttenuationgives one listener better or worse hearing. The default is flat. - Listener angle.
AudioListener:SetAngleAttenuationworks 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.