Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What
Brings audio mixers functionality to the engine similar how they works in unity or generally any other software I believe. Thus:
Why
Fixes #5462 and space-wizards/space-station-14#22710, corresponding PR to SS14 will fix some other issues there, generally a must-have tool for the engine.
Technical details
Underlying tech
This audio mixers implementation does not use OpenAL auxiliary slots (if they even can be used to implement this) or any other fancy low-level stuff. Instead, simple mechanism of storing references in mixers and sources to each other is used, and when gain of any mixer is changed, all connected mixers and sources modify their gain value (see
AudioMixer.cs
). However, I see no problems to seamlessly re-implement internal work of audio mixers to use OpenAL auxiliary later, this will need to be done to support the audio mixer effects as well.MixableAudioSource
I did not dare to put mixers support into AudioSource, since it is a rather thin interface with OpenAL, so the MixableAudioSource wrapper is used to support audio mixers. AudioComponent has now reference to IMixableAudioSource, not IAudioSource.
Audio mixer prototypes
This is a way to have "audio categories", game can define any number of mixer prototypes and use their IDs to assign corresponding mixer to audio sources. This replaces dubious pattern of handling subscriptions to CVars for every source and for the most cases this is nearly impossible to do manually. "Prototyped" audio mixers can be assigned via AudioParams, so it is really easy to manage. There are also a problem of many sources not having any mixers assigned at the moment in SS14, but customizable default mixer can be handy in this case.
Plain object mixers
AudioMixer is a plain object and AudioSource counterpart, so exists only on client side and managed by AudioMixersManager. Manager creates custom mixers and stores mixers from prototypes, so only one AudioMixer instance corresponding to any AudioMixerPrototype id can exist.
Entity-based mixers
AudioMixerComponent is a counterpart of AudioComponent and they are used together. Mixer component on client obtains reference to plain object mixer and system will assign this mixer to internal audio source component when needed. Mixer component fully supports synchronization, so can be assigned to audio sources on the server side, Mixer components are spawned on separate global entities.
Entity-based mixers from prototypes problem
The concept of "prototyped" mixers conflicts with entity-based mixers in terms of lifetimes.
My first implementation of this was lazily creating mixers for prototype when requested, newly created mixer then stored in dictionary indefinitely. Unfortunately, some SS14 integration tests does not like this idea when any entity creates more other entities than deletes after got deleted.
This implementation creates all mixer entities from prototypes at start of the simulation (check out the funny way how system knows when its time to spawn entities) and when entities flushed. Set of such entities exists separately on client and server though because single-player games may exist and (probably) entities from server may not be sent to the client fast enough. The problem with this implementation is that other SS14 integration test (DeleteAllThenGhost this time) can't handle that deleting all entities on the server leaves mixer entities on client.
So this problem is relevant and PR probably should not be merged like this, either mixers should be implemented differently (but I don't know how at this point) or SS14 integration tests should be adjusted.
Discussion
As you can see, there are plenty of debatable decisions in this PR, so maintainers may fell free to discuss and request changes to implementation here, or for quicker communication in discord (
stalengd
, DM or ping).PR to SS14 repo
space-wizards/space-station-14#33816