Audio Manager Design

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By StefanoGrossiNature

I am writing my own audio manager for my Game and it will add a variable number of AudioStreamPlayer/AudioStreamPlayer2D to the SceneRoot.
I’ve read alot in documentation but i’m not going down to read the C++ source code; what i would like to know is what Godot do with every AudioStreamPlayer added
to the SceneRoot. For example: does it send signals to everynode? How many functions are called?
I don’t override any function like _process() etc (there is no script attached) but i am reading that Object class receive alot of notifications,so i suppose
for everynode Godot calls alot of functions.

The reason is that i would like to know how many AudioStreamPlayer i can add to have a reasonable limit for the audio manager, balancing it without making
heavy work for the cpu.

If there are docs wich explain what happen for every Node/Object in the SceneTree please send me the link (i have just found few but not detailed).

Thank you in advance

*EDIT: We ended up with a interesting conversation about sound system design and audio manager implementation so i suggest anybody wich is making one to read everything.

While I can’t answer the details of your question, I do have some experience with an in-game AudioManager class. In my case, any part of the game can just blindly request the AudioManager to play a given sound. With that, the AudioManager checks to see if it has an available (not in use) AudioStreamPlayer. If so, it uses it to play the requested sound. If not, if creates and caches an additional AudioStreamPlayer to play the sound. As soon a given, cached AudioSteamPlayer is finished playing its sound, it’s available to be used by the next request.

With this scheme, the maximum number of cached AudioStreamPlayers is dynamic, and equal to the maximum number of simultaneously played sounds within a game session. In practice, that scheme worked well for me.

jgodfrey | 2020-12-03 15:17

Thanks for sharing it; i’ve re-written my audio manager 3 times to evolve it, and basically it work in the same way as yours but with some plus features aimed to get as less as possibile AudioSteamPlayerS at the same time. My manager actually (i am writing the last version just now) can play any sound at any time(as yours) but without adding any AudioSteamPlayer at runtime to avoid cpu loads in critical parts.

If i may ask,how many AudioSteamPlayer Nodes you can have simultaneously in your SceneTree? Said in a peak max situation? So i can have an idea.

StefanoGrossiNature | 2020-12-03 16:33

I really don’t know for sure, but I’d guess the peak in my case is likely in the range of 5-7 independent AudioStreamPlayers. While I never found it necessary, it’d be really easy to request that the AudioManager precache a given number of players at the start of the game to mitigate some of the performance hit you mention, and then just increase the cache if/when necessary throughout the game.

One other point in case it’s interesting. In my case, the SFX and Music run on two separate AudioBuses. With that in mind, I dedicate an AudioStreamPlayer to one of the two buses upon creation. So, effectively, a given player is dedicated to playing either SFX or Music during a given session.

I don’t recall why I ended up doing that, but I have a vague recollection of running into a problem with changing the bus that was assigned to a given player after-the-fact (though, maybe I’m misremembering the situation).

jgodfrey | 2020-12-03 17:18

That’s very useful jgodfrey. indeed i am still a little struggled to make a final architecture in my manager. 5-7 AudioStreamPlayers sounds fine i guess; in my Game,wich is a racing game with 20 players on screen at same time,i had to find a way to cutoff the uneccesary sounds at runtime, for example to avoid unecessary car sounds(mostly not hearable).
I’ve ended up just 1 hour ago with dynamically use of AudioStreamPlayers and stopping the unused one,with a complex structure that divide sounds by type (so i can configure it even for future games).
I underestimated how critical was this part,i’ve spent 4 days now doing it and it’s not still finished.

In my game btw i will end up playing 11/12 AudioStreamPlayers at same time,hopefully this will be not too much.

Thanks for your help!

StefanoGrossiNature | 2020-12-03 21:36

I’d guess 11/12 AudioStreamPlayers won’t be a problem for the engine itself, but I wonder how many sounds can be overlapped at one time and still be heard “as intended” by the player? That is, at some point, I’d think that too many overlapping sounds would becom non-distinct and just “muddy” to the player.

If that becomes a problem, I might consider something like:

  • Decide on the maximum number of simultaneous sounds you want to allow
  • Assign a “priority” (importance) value to each individual sound
  • When a sound request comes into the Manager…
    • If your max overlapped sounds hasn’t been reached, just play the requested sound
    • If the max has been reached, see if a sound with a lower priority than the request is currently playing. If so, stop that sound and use its player for the new sound.
  • If the all sounds playing are of higher priority that the request, just ignore the request

Something like that would allow you to set a cap on the number of sounds being played simultaneously, while ensuring that the most important sounds take precedence over the less important sounds.

jgodfrey | 2020-12-03 21:50

Indeed jgodfrey, seen that you understand exactly what are the problems i want to explain you quickly how my system work,so maybe this can help other ppl too.

I setup a number of channels at the beginning of AREA of game (not entire game,because for example in a gdr sounds indoor are different from outdoor etc).
You may create a fixed channel (for example for a sound that never change,like a background music) and a MULTICHANNEL.
A MULTICHANNEL is dynamic: you choice the number of sub-channels it have and you may play any sound on it,the system will automatically find a free slot and play on it.
You may have any number of multichannel or singlechannel,so you can manage the sound based on what you really need.
If the slot its not found(all subchannels are playing)…here it come the trick.
Your suggestion yesterday made me think alot,specially your idea about priorities wich is smart in my opinion. But since i don’t want sounds to be cutted off during gameplay,or un-necessary sounds being played (as you said too),i’ve ended up with this technique (wich of course,is always based on the cap that you also mentioned,a max number of simultaneous sounds limit ).
If all slots are busy(playing) then the system will replace the MOST OLD SOUND PLAYED(and not based on priority because in “real world” it’s hard to choice wich sound will have priority,in my opinion),so my FRESHNESS system will just check wich sound in the slots it’s the “oldest” and replace it. This should work because usually you introduce a new sound dynamically when a new event come,and this apply specially for looped sounds wich can become “old”.
Plus: there is another trick: when you play a sound,you may set that sound to HIPRIORITY,and that sound can’t be replaced in any case. So for example in a gdr if you have a water sound(looped) and you want it to be always heard,you just set it HIPRIORITY.

What do you think about that?

It’s your idea about priorities that made me think about the freshness system,wich i think in “real world” it’s more pratical,but of course i can tell that ONLY after i will test the final game (now it’s still too early) with all sounds.

Today i will do a quick refresh of my old school books,seen that in 90’s era they had very limited amount of channel and they made wonderful games.

I’ll post a comment if i find new ideas.

Thanks for your help i appreciate it

StefanoGrossiNature | 2020-12-04 07:57

Your current system design sounds pretty flexible. Your sound freshness idea sounds interesting, and probably could work well based on the sound design of your game and other details.

Originally, I was concerned that a high-priority sound (like Music for example) could be seen as the oldest sound and stopped to play some minor, unimportant ambient sound, but it seems you have that handled via your HIPRIORITY concept (and, probably the different channels concept).

I’d be interested to hear how it works out in the end. Good luck!

jgodfrey | 2020-12-04 16:35

:bust_in_silhouette: Reply From: jgodfrey

Posting an answer here so the question looks useful to those looking at the forum’s high-level list of questions.

Refer to the lengthy conversation in the comments of the question above.

One other comment. The question might be more useful to others if the title was changed to something more appropriate. Maybe Audio Manager Design or similar?

Completely up to you though.

jgodfrey | 2020-12-04 16:37

Here we go.

Btw just to make a final update i have spent half of a day in theory and i’ve ended up (after reading some good books about audio systems) that my system was too much complex. I’ve selected just two implementations and i will finish the final version tomorrow wich will be enough for my game.

There are many things that can make an audio system VERY COMPLETE,but of course you need to write what is needed for your game,but just if someone is curious you can make for example a ranking system where the manager will cutoff sounds (when all slots are full) not just based on their priority but for example based on their volume(the lower volume will be cutted of 1st),their distance from listener and so on…That will be more accurate.

I also re-considered your idea about priorities and i will make it in my manager,i’ve abandoned the “fresheness” instead(you were right!).
I can continue talking for hours but i just suggest if someone it’s interested to read Game Programming Gems 6 or 7 i don’t remember where there are interesting topics about audio.

For now,i will cut it here.
Thanks jgodfrey!!

StefanoGrossiNature | 2020-12-04 17:37