Roblox's New Audio API: A Somewhat Deep Dive

Hey there. I’m Koolaid, and approximately about a few days ago as I am writing this, Roblox released their new audio API out of studio beta. Overall, it’s really neat in it’s own way, and I have learned how to use the new API for my projects. However, for people using the Audio API for the first time, it can be quite tricky to understand, so I wrote this guide to help you learn how to use Roblox’s audio API correctly.

:memo: The Basic Audio API Diagram

I have created 3 diagrams to visualize how the audio API works.

This is the basic setup of an AudioPlayer that plays music. Inside the Camera, there is an AudioListener and an AudioDeviceOutput object. This is how sounds are played in the 3D world.

The arrows pointing to each graph represents a Wire object. It comes out of the Source instance (left) to the Target instance (right). Wires send sound data to other audio objects if correctly configured. The following connections using Wires should be valid:

This list is displayed as SourceInstance > TargetInstance

  • AudioListener > AudioDeviceOutput

  • AudioPlayer > AudioEmitter

  • Any sound effect object > Any other sound effect object

  • Any sound effect object > AudioEmitter

  • AudioDeviceInput > AudioEmitter

  • AudioPlayer > AudioDeviceOutput

  • AudioListener > AudioEmitter

:sparkles: Applying Effects

This is a diagram which visualizes how different audio modifiers are applied. For this, we connect an AudioPlayer to the AudioReverb object using a Wire, and then do the same thing but we connect the AudioReverb object to an AudioEmitter using another Wire. This will give our sound a reverb effect.

:studio_microphone: Utilizing Voice Chat

This last diagram visualizes how you can use Voice Chat with the Audio API. For this, we create an AudioDeviceInput object that is connected to an AudioEmitter object via a Wire. We set the Player property of the AudioDeviceInput to the player we want to retrieve the sound from, and we make sure that they’re not muted by setting the Muted property to false.

:scroll: Scripting

:camera::loud_sound: Camera Listener Script Setup

Now that we got through a visualization on how the Audio API works, let’s set it up! First, we need to add a way for the game to pick up audios and make it so that everyone can hear it. To do this, we add this code which creates an AudioListener and an AudioDeviceOutput object inside of the Workspace.CurrentCamera. We hook both the device output and the listener together with a Wire.

:desktop_computer: This script functions properly when it’s RunContext is set to Client or if it’s a LocalScript.

-- Get the camera currently being used by the Workspace service
local camera = workspace.CurrentCamera

-- We add the necessary audio objects inside the Camera
local listener = Instance.new("AudioListener", camera)
local audioOut = Instance.new("AudioDeviceOutput", listener)

-- We make a new wire inside the listener and connect the two audio objects together
local wire = Instance.new("Wire", listener)

wire.SourceInstance = listener
wire.TargetInstance = audioOut

This is how we make audios play within the world.

:loud_sound: Playing Sounds through Scripts

While doing this without code is a way to setup sounds with the Audio API, you can also do something similar via scripts. For this script, we create an AudioPlayer and an AudioEmitter inside of a Part and wire them together.

-- A function that wires a Source sound instance to a target sound instance
function connectDevices(source, target)
	local wire = Instance.new("Wire")
	wire.Parent = source
	wire.SourceInstance = source
	wire.TargetInstance = target
end

-- Make an AudioPlayer that plays Life in an Elevator
local audioPlayer = Instance.new("AudioPlayer", script.Parent)
audioPlayer.AssetId = "rbxassetid://1841647093" -- Change the ID to anything you want (Optional)

-- Make an AudioEmitter that will play the sound
local emitter = Instance.new("AudioEmitter", script.Parent)

-- Connect the devices
connectDevices(audioPlayer, emitter)

-- Play the song
audioPlayer:Play()

When running the game, the game should now play Life in an Elevator, a song from the Roblox toolbox.

:studio_microphone: Basic Voice Chat Setup

The code below is a recreation of Roblox’s default voice chat setup, which can be used as a template if you want to add some modifications, like add an audio effect for example.

-- Function that automatically creates a Wire
function connectDevices(src, target)
	local wire = Instance.new("Wire")
	wire.Parent = target
	wire.SourceInstance = src
	wire.TargetInstance = target
end

game.Players.PlayerAdded:Connect(function(player)
	
	-- Create a new AudioDeviceInput
	local micIn = Instance.new("AudioDeviceInput")
	micIn.Parent = player
	micIn.Player = player
	micIn.Muted = false
	
	-- Assign a CharacterAdded event incase the player dies and respawns
	player.CharacterAdded:Connect(function(character)
		
		-- Make a new AudioEmitter with its Parent being the Character
		local emitter = Instance.new("AudioEmitter")
		emitter.Parent = character
		
		-- Connect the devices together
		connectDevices(micIn, emitter)
		
	end)
end)

In this script, when a player joins, we make a new AudioDeviceInput object inside of the player that joined the game, set it’s Player property to player, and automatically set Muted to false for the AudioDeviceInput.

Next, we connect a CharacterAdded event to the player incase the player resets or dies from losing health. This event creates an AudioEmitter inside of the Character model, and connects the AudioDeviceInput object to the AudioEmitter. That way, other players can hear that player speak through their microphone.

:loudspeaker: Basic Intercom System via the Audio API + ProximityPrompts

This script is a basic setup for an in-game intercom system.

-- A table for currently speaking players
local sessions = {}

-- Function that creates and returns a Wire
function connectDevices(src, target)
	local wire = Instance.new("Wire")
	wire.Parent = src
	wire.SourceInstance = src
	wire.TargetInstance = target
	return wire
end

-- A cleanup function which removes a player from the sessions table
function cleanup(name)
	print("Cleaning up "..name.."'s intercom session")
	local session = sessions[name]
	if session then
		session.micDevice:Destroy()
		session.emission:Destroy()
		session.wiring:Destroy()
	end
	sessions[name] = nil
end

-- Connect an event for when the ProximityPrompt is triggered
script.Parent.ProximityPrompt.Triggered:Connect(function(player)
	
	-- Is the player not in a session?
	if not sessions[player.Name] then
		
		-- Make a new microphone input object
		local micIn = Instance.new("AudioDeviceInput", player)
		micIn.Name = "speakerDevice"
		
		-- Make a new emitter inside of the Part
		local emitter = Instance.new("AudioEmitter", script.Parent)
		emitter.Name = "emitter"
		
		-- Set the microphone speaker to the interacting player
		micIn.Player = player
		
		-- Connect the microphone and emitter together
		local wire = connectDevices(micIn, emitter)
		
		-- Add the player to the session list
		sessions[player.Name] = {
			micDevice = micIn,
			emission = emitter,
			wiring = wire
		}
		
	else
		
		-- If there's an active session, clean it up
		cleanup(player.Name)
		
	end
end)

In this script, we have a sessions table, which lists all players that are speaking via the intercom system. We have 2 functions, one name connectDevices which makes a Wire and connects the src and target instances together and returns the newly created Wire.

Next, we have an event connected to a ProximityPrompt in which when it’s interacted with, it allows the player to speak.

In this event, we check if the player who interacted with the prompt is not currently speaking using the system. If this is true, then we make a new AudioDeviceInput and a new AudioEmitter inside fo our Part. Then, we connect the two devices together by calling connectDevices(micIn, emitter) and create a new dictionary inside our sessions table, which will have our AudioDeviceInput, AudioEmitter, and Wire to clean up later.

If the player is already speaking using the intercom, we call the cleanup function providing the player’s name to destroy the player’s AudioDeviceInput, AudioEmitter and Wire. That way, we can stop emitting any output from the player’s microphone. This also removes the player from the session list by setting the data to nil.

Conclusion

And that basically wraps it up! I hope this guide helped you understand how the Audio API works and how to use it. I’ll add more stuff here when I get the time, but for now, feedback on this tutorial is much appreciated!

11 Likes

This tutorial only tells you how you can replicate the default Sound Instances using the new Audio Api, you didn’t say anything about the possibility to connect AudioPlayer right to the AudioDeviceOutput. Or that you can connect AudioListened to AudioEmitter which would make a microphonw effect. Tho i didn’t read the whole post only some parts so my reply might be wrong.

EDIT: looks like the author is adding more to the tutorial.

@BubasGaming bruh

Cool beginner tutorial. Definitely gonna add a voice chat radio system to my projects.

3 Likes