LoudFilter - Filter out loud audio

LoudFilter

LoudFilter is the perfect solution for detecting the average loudness of a sound on the server. It is especially useful for filtering out audio that is too loud.

Use case

If you have ever played a game that gives the player some sort of ability to play songs, then you have probably experienced extremely loud audio. This is something that can be difficult to moderate automatically, especially since you are unable to detect how loud a sound is purely on the server.

Thanks to this module you are able to detect the average loudness of a sound meaning you are able to stop it from being played in the first place.

Method

Since we are unable to check PlaybackLoudness on the server, we instead send the sound to every player in the server and let them report the loudness. This might seem like a bad idea, but since we are only returning the median an exploiter can only have minimal effect on the result.

Docs

LoudFilter.New
Creates a new loudness state with the specified parameters

@param audioId {Number} The id of the audio to scan
@param duration {Number} How long to scan the audio for
@param amount {Number} How many instances to scan
	
@returns {LoudFilter} The loud filter state

LoudFilter:GetLoudness
Gets the loudness of the previously defined sound

@param volumeBound {Number} Any number higher than this is ignored
	
@returns {Number} The average loudness of the sound

Example

local LoudFilter = require("LoudFilter")
local id = 0000

local start = tick()

local duration = 2
local amount = 2
local bounds = 1000

local filterState = LoudFilter.New(id, duration, amount)
local loudness = filterState:GetLoudness(bounds)

print("Average loudness:", loudness)
print("Time taken:", tick() - start)
print("Duration:", duration)
print("Amount:", amount)

if (loudness > 800) then
	-- Do something
end

Credit

Thanks to Dummiez for their audio scrubbing method - How can I get a song's max playback loudness? - #22 by Dummiez

Feedback

If you have a better method for detecting the average loudness, or a general suggestion on something in the module code feel free to contact me on DevForum.

18 Likes

It still seems like a bad idea. Without checking the source code, but interpreting what you say: If every player’s average value is taken into account to calculate a new average, it can still be prone to exploiters.

For example:
If 10 players report the average loudness value to be 10, but one exploiter says it’s 10000, the average value would be 918-ish, not optimal. If the algorithm your code uses generate the same output for the same input, you should much rather take into account what most players report, instead of the average value.

2 Likes

The algorithm can generate different outputs based on what Roblox reports. So that method isn’t really feasible.

I just tested the results myself and your theory seems correct. I’m going to be changing from the mean value to median instead.

It’d be better if this was done in a LocalScript with the sound filtering being done on a player-player basis. Doing so will easily mitigate the issue with exploiters and limit their flexibility with exploiting the sound loudness filter system.

Yeah I’ve thought about that as well. I figured this might be more optimal in case you would want to access the loudness on the server. I did some testing with the current method and I couldn’t find a scenario in which the exploiter could affect the loudness returned (unless the player count was very low).

Better to be prepared for a case like this happening than not, though. I’d definitely take advantage of this resource if there was a way to filter on a client-client basis. So far, it looks pretty great; keep up the good work!

1 Like

Wouldn’t CompressorSoundEffect be able to clamp audios which are louder than the threshold? You can set gain to 0 so it doesn’t amplify.

1 Like

I’m not too familiar with it, however I ran some tests on a few audio samples that vary in loudness. The results are not too consistent, in certain cases the sound is still loud, however I might have had the wrong properties.

Interesting either way.

Use the 1.5x IQR algorithm to filter out any outliers.