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

@ReallyLongArms We’re using this new API heavily in our game - and it’s mostly great. I’m just a bit concerned regarding performance. For example, say I have 50 (or say 200) sound emitters each of which has an AudioReverb and perhaps one or two other effects connected to them - is this ok?

In Fmod Studio, you would route all these sounds through a single reverb bus - so you’d be able to have one reverb effect for 50 sounds - but as the spatialization of the sound happens at the end of the effect chain, we have to place the AudioReverb before the AudioEmitter. This feels as though it is suboptimal, potentially fatally so.

Can you confirm if this is the case? If so, can you suggest any alternatives (except, preferably, not using this API as we’re pretty invested in it!)

If AudioEmitter could appear in the middle of the effect chain (as the Spatializer can in Fmod Studio) we would be very happy.

Also - can we have AudioPanner? I think we can build this with AudioChannelSplitter, 2 (mono) - 4 (stereo) Faders and AudioChannelMixer but this seems overkill.

Is it possible to make audio emitters emit their sound with X delay time?

For example, lets say i use a single AudioPlayer:Play(), with the audio player connected to different emitters

@WoloPoints You could wire the AudioPlayer to several AudioEchos, one before each AudioEmitter

In the old system I just have to create a master sound group, then a child sound group for the gun sound effects. Now the gun SFX group can have its volume set individually while also adhering to the master volume because of how it multiplies all the volumes together.
What am I supposed to do with the new API? Create a listener entirely just for gun sound effects that then connects to a fader for the gun sound effect volume, then that fader to the master fader which then finally connects to the AudioDeviceOutput? That’s is so unnecessarily cumbersome.

@Fezezen yes you’d create an AudioListener to hear the gunshots, then apply volume/effects adjustments after the listener. It’s definitely more instances, but this is what Sound + SoundGroup were doing under the hood, hiding the details.

The big thing this buys you is the ability to have branching signal flow. In the Sound API, many sounds can route to one SoundGroup – but you couldn’t have one Sound go to several parallel SoundGroups.

On another unrelated note, we’re struggling with the setup here because of the way the emitter is the source of the sound at the end of the pipeline. With Fmod Studio, you can (at least conceptually) emit lots of sounds in different locations - such as with the scatterer instrument - with a single chain of effects/mixers. The spatialisation is then applied as the last step, after the effects have been applied (in principle).
With this the way your system has been implemented, if we wanted to scatter sounds around with different positions and all sharing the same effect chain, we have to duplicate that whole chain for each sound we play. This feels sub-optimal.

@Ed_Win5000 you could give the AudioEmitters a particular AudioInteractionGroup – this constrains which listeners are capable of hearing them. Then, if you make a single AudioListener with the same interaction group, and connect that to the reverb, you don’t have to do the reverb pre-emission

i can accept the way it’s currently being structured but some of my sounds had this crack which is weird personally

@pankii_kust we found a bug that causes freshly-created emitters/listeners to “click” when they are using a custom distance or angle attenuation curve – that should be patched soon

1 Like

Thanks @ReallyLongArms - that’s really helpful. I’d forgotten in the complexity of it all that AudioListeners have wires out. Obviously there’s some cost to AudioListeners, but is the comparable cost reasonably low versus a single listener if they’re hearing mutually exclusive sets of emitters?

I notice that a few of the functions on AudioListener are missing docs, namely GetInteractingEmitters (which is pretty obvious) and GetAudibilityFor (which is less so).

but is the comparable cost reasonably low versus a single listener if they’re hearing mutually exclusive sets of emitters?

Yeah this is pretty cheap; each emitter & listener pair uses a panner + volume fader under the hood (to implement directionality & attenuation respectively). This is all math we would’ve been doing anyway

I notice that a few of the functions on AudioListener are missing docs, namely GetInteractingEmitters (which is pretty obvious) and GetAudibilityFor (which is less so).

I think we just haven’t gotten around to adding docs for these yet; we can tackle that.
GetAudibilityFor reports the distance & angle attenuation (as a number between [0, 1]) that an emitter experiences relative to a listener, or vice versa (both classes have a similar, symetric method)

1 Like

@ReallyLongArms Hope you don’t mind a random bug report here:

I think the way Compressor is set up is incorrect, at least compared to my expectations from Fmod Studio. If you have a compressor with no side chain, then I’d expect that none of the parameters except Gain have any effect. The Threshold property shouldn’t do anything. In reality, in this situation, Threshold behaves the same as Gain and modifies the output volume.

So if you create an AudioCompressor with no sidechain and set the Threshold to (say) -50dB then the sound becomes almost inaudible.

This may be down to the defaults - does having no sidechain get interpreted as a 0dB input rather than a -∞dB input?

A disconnected wire as the Sidechain input doesn’t resolve this problem.

Hey @Ed_Win5000 – no worries

AudioCompressor compares the input stream against an analysis stream. When the analysis stream goes above the Threshold, the compressor clamps down on the input stream (reducing the volume an amount determined by Ratio)

When something is wired to the “Sidechain” pin, that stream gets used as the analysis stream. But, when nothing is wired to the “Sidechain” pin, a copy of the “Input” stream is used instead.

So I think the behavior you’re describing is expected

I just tested it real quick and as for now it really slows down my experience that is using a bunch of moving sound emitters – Will there be an option to maybe calculate only the nearest sounds and ignore the ones that are far away?

You’re right, I was misunderstanding that. Sorry for wasting your time there. A bit more detail on the docs around using sidechains and not could be helpful. The example shows using a sidechain, but there’s no real description of how they works or how it works if you don’t have a sidechain (or even if you have multiple sidechain inputs?)

question, do you know how I could convert the in-game Loudness to dB?

@ReallyLongArms I think you may have mentioned a known issue somewhere that’s similar to this, but we’re coming across situations where we hear slight pops caused by sounds starting playing with non-0 level (e.g. often caused by starting with a TimePosition that isn’t 0). Fmod normally fixes this with a quick ramp on sound channels when they start, over a few milliseconds. I’m not sure if this is something you can do automatically, but we don’t have an effective way to do it ourselves as we can’t update audio volumes at sub-frame frequencies.

Related to this: We’d still love a way to modify sounds at higher frequencies so we can synchronise tracks together.

Hey @Ed_Win5000 – a flag to fix some of those pops & clicks went into v676 – unfortunately I haven’t been able to flip the flag yet due to some platforms lagging behind :sad:

Related to this: We’d still love a way to modify sounds at higher frequencies so we can synchronise tracks together.

Yeah; I hear you loud and clear – the current scripting model only allows modifying properties during each frame. We’d like to add some “pre-planning” API that lets you schedule changes to happen in advance with tighter (better-than-framerate) timing guarantees. I can’t offer any firm dates, but it’s something we want really bad :sweat_smile:

question, do you know how I could convert the in-game Loudness to dB?

Hey @onlyalexicon, something like this should do it

local function toDecibels(amp : number) : number
   return 20.0 * math.log10(amp)
end
2 Likes

I had to go digging for this response because OP says that Sounds can be picked up by listeners.

Can OP be updated to clarify this?

Sorry I can see how that’s confusing – when I said

if parented to a Part or Attachment , it will also behave as a 3D audio emitter that can be heard by your listener.

What I didn’t make clear is that the Sound API uses a single, global listener, controlled by the SoundService:SetListener method – so it’s not an AudioListener instance, but it’s still “your listener” (colloquially speaking)

1 Like

Hoold up - does this mean public address or tannoy systems are possible?

Like speaking and having your voice broadcasted around a building with multiple speakers? Yes.