New Audio API [Beta]: Elevate Sound and Voice in Your Experiences

awesome, hoping the plan goes through.

@ReallyLongArms Any word on when volumetric audio will be supported with the new AudioEmitter API? It’s severely disappointing not having support for it at the current moment. I was contemplating converting to the new system with my team to take advantage of the lovely new features, but not being able to make “stereo” audio in the 3D gameworld is a massive setback.
Are there any temporary solutions to volumetric audio with the current API? Any panning filters planned? etc.
I’d love to use the new system, but the lack of an ability to split up the L and R channels of a stereo file is really disappointing…

  • Panzerv1
2 Likes

Hey @panzerv1, at the moment your best bet is probably dispersing emitters around the surface of a part; something like

local fader : AudioFader = script.AudioFader
local part : BasePart = script.Parent
local rng = Random.new()
local pointCount : number = script:GetAttribute("Points") or 500

local function getLocalPoint() : Vector3
	local cframe = part.CFrame
	local bounds = part.Size / 2
	local radius = bounds.Magnitude
	local vec = rng:NextUnitVector() * radius
	vec = cframe:PointToWorldSpace(vec)
	vec = part:GetClosestPointOnSurface(vec)
	return cframe:PointToObjectSpace(vec)
end

local function wireUp(src : Instance, dst : Instance)
	local wire = Instance.new("Wire", dst)
	wire.SourceInstance = src
	wire.TargetInstance = dst
end

for i = 1, pointCount do
	local attachment = Instance.new("Attachment", part)
	local cframe = part.CFrame
	attachment.Position = getLocalPoint()
	local emitter = Instance.new("AudioEmitter", attachment)
	wireUp(fader, emitter)
end

emitters and listeners are just panners under the hood, so this should be pretty cheap, and it generalizes to any part shape!

We’ve discussed adding “Channel Splitter” or “Channel Combiner” instances so that you can split out channels and route them to particular emitters – the main complication is that we don’t want the API to behave differently depending on what output device you’re using, and there are a couple of effects that use a different number of channels depending on what your hardware supports.

1 Like

I understand that Surround sound such as 5.1 setups are very rare for the platform, but not having the ability to take one sound id instance and pan the channels of it in any way is a bit limiting. The core tools I need as a sound designer are volume, EQ, and panning. Without direct control of panning for even a stereo file is very limiting.
Stereo output is the most common speaker / headphone output in gaming.

I was talking with my boss (programmer) and we realized that multiple emitters are panning on one part because there was no phase cancellation.

Is there a possibility of at least L and R channel panning in the near future? My sound design in our game had to take a 6 year setback in terms of quality and it hurt. We were sounding like an up to date 2024 game, but now we have to go back to 2018.

I really appreciate the response so soon and I hope the future holds some improvements for the API because it has SO much good stuff.
Cheers,

  • Panzerv1
1 Like

Is there a possibility of at least L and R channel panning in the near future?

This would be possible with a Channel Splitter instance – something that takes a single input stream and gives you the individual channels to be processed or modified as needed.

Currently, when you wire anything to an AudioEmitter, all of its channels get emitted from a single location, which makes it sound effectively mono.

We’re aware of the limitation and hope to solve it in a way that won’t design us into a corner long-term

1 Like

There is currently a limit when playing more than ~300 audio sources (regardless the number of audio emitters) which is really a bottleneck for my system. Adding more than 300 audio sources linked to emitters lead to some of them not playing at all.

I’ve tested in a number of ways, but for my application i use around 15-20 sounds per source emitted trough 6 speakers (each unit). The volume and other properties do get applied to the sources but the sound is not coming off from sources added after the ~300 ish limit i suppose.

Edit: For context all the emitters are not modulated at all, and there is only a reverb process done after the general audio is captured by the audio listner.

Hey @cellork1; this limitation is present with Sounds too, but we try to cull/drop the least audible audio files when too many are playing at once. AudioPlayer doesn’t correctly take audibility into account, which is why you might notice it more prominently with the new api.

We have a flag to fix that, but it caused some other issues and had to be disabled – hoping to get that re-enabled soon

5 Likes

I have one last question about implementing a personal optimization procedure until you guys do your thing.

Lets say i have 300 sounds. The 301st sound, played, will not produce an output in this case. If i were to “:Stop()” the 300th sound, will that make the 301st sound produce an output again ? (like making room for it among the sounds that can be heard).

(Trying to purge trough audioplayers and “:Play()” / “:Stop()” only the ones that are close enough to the player.)

Yeah I imagine that would work – that said, ideally it’s not something you’d have to worry about doing manually! Sounds that are completely inaudible (e.x. their volume is 0, their emitters are really far away, etc) should not contribute to the total count, yet currently they do.

Do you have a ballpark number of concurrent audio files you’d need? We can up the cap to 400 until we land the audibility fix

If i were to really go overkill, 30 sounds per unit x20 will result around 500 sounds. But firstly I’ll try to implement my optimization, without making you risk breaking other engine functionalities.

I’ll get back with a reply once I’m done.

1 Like

My conclusion: Its… weird… to say the least.

Playing and stopping sounds on the fly does and does not work at the same time. When first loading ~57 audios, not all of them produce an output. When purging them one by one by moving the camera randomly, some do not load. But when i get far enough to stop all of them, after i return to load the closest unit all the sounds caught do get played (and again moving the camera around them by loading/unloading randomly still doesn’t work until i unload everything).

Edit: Also i do experience lag spikes when loading/unloading the sounds. (nevermind, adding a task.wait() between executes seems to fix it)

This is a very great release! Although I do have a concern. AudioEmitters do not work with Volumetric Parts, meaning the origin of the audios basically start from nothing.
I am working on a game where I am composing an indoor ambience, and I am using Parts as the volume of the Sound. DistanceAttenuation does not respect the Part’s volume, and instead fades from its origin!

@aaxtatious This is a good point. FMOD (the underlying library Roblox uses) has a concept of “Sound Size” that I believe addresses this issue. This allows you to be ‘enveloped’ in the sound when you’re within a certain radius of the sound.

Taken literally, what you’re requesting could be addressed by setting the attenuation curve to start attenuation from a certain distance from the object rather than from 0, which may have some of the effect you desire? This wouldn’t have quite the same effect as the sound size option.

For the sake easy threading I wanted to connect your old feature request here to the release post :slight_smile:

1 Like

Feedback is a real thing in the real world too where a microphone picks up a sound from a speaker and the speaker replays an amplified version of it into the microphone creating a loop, where every replay is louder

Yup! In some sense, emitters and listeners exhibit the same behavior as real-world speakers and microphones – but in reality, speakers & microphones can get blown or damaged – in the digital world, things can just keep getting louder :loud_sound: (barring floating point shenanigans)

The documentation told me that if an AudioEmitter is not part of a BasePart, Attachment, Camera or PVInstance, it cannot make any noise.

AudioEmitter and AudioListener infer their CFrame (position & orientation) from their parent – if they don’t have a 3d position & orientation, the audio engine doesn’t know where to emit or listen from

1 Like

This new Audio API opens up a ton of new possibilities like a hypothetical PSTN/landline or an intercom

Hey I’ve recently changed it to use my own Voice setup how do I change my volume? I can hear people from far away I’ve search it a little better I found SetDistanceAttenuation which controls how an audio emitter’s volume changes with distance I just dont know if this is the right thing I need to use