Best way to stop volume increase when playing sounds at the same time

TrunX

Member
I think it's a well known problem that sound effects can get uncomfortably loud when they are played several times at the same time.

I have two solutions in mind and would like to hear which one is better and if there is a better alternative solution out there.

1)
Code:
audio_stop_sound(argument0);
var snd = audio_play_sound(argument0,argument1,argument2);
audio_sound_gain(snd, snd_volume, 0);
This would hinder any sound to be played mor then once at the same time

2)
Code:
if ds_list_find_index(snd_list,argument0) == -1
    ds_list_add(snd_list,argument0);
else
    exit;

var snd = audio_play_sound(argument0,argument1,argument2);
audio_sound_gain(snd, snd_volume, 0);
snd_list gets emptied at the end of each step.
This would allow the sound effects to be played with at least one frame of delay in parallel.
 

Yal

🐧 *penguin noises*
GMC Elder
I don't remember the name, but there's a function that lets you set the number of sounds that can be played at once across ALL sounds in the game (I think it's audio_set_channel_num or something like that). Running that at startup to limit max sounds is perfect for cases like this... you just need to make sure to set your sound priorities properly, since that's what's limiting what sounds get cut out (music should have the highest, followed by alerts like "your health is low", followed by explosions and other stuff that gets loud if too stacked).

Another thing you could try is using audio_sound_pitch() to play repeated sound effects at slightly randomized pitches (e.g. 0.8 ~ 1.2 range), this makes the sounds slightly different even when the same sound is played several times at the exact same time. This makes things like footsteps sound more natural since they're not robotically identical each time, but it doesn't work for EVERY sound (e.g. powerup jingles and voice acting sounds weird if randomly pitchshifted). I usually make separate scripts for pitched and vanilla sound effect playing.
 
M

Misty

Guest
In real life, when you play a sound over and over again, it gets uncomfortably loud. Such as jackhammers and such.

If you want to stop sounds from being repeated in the same frame you need a global variable called global.SOUND then you put it as an array like global.SOUND[name of sound-100000] to check if its already playing. You put the -100000 because object ids start at 100000 I think, and you cant have an array more than 32000. This has never been tested, but should work, theoretically.

If it doesnt work its because sound ids are different offset than object ids, then explore where sound ids are offset by.
 

Phil Strahl

Member
The way I do this is might be overly complicated but in principle it works like this:
I have an object ctrl_sound that is persistent and it holds a ds_queue. When an instance wants to play a sound, instead of playing it itself, it queues the sound with ctrl_sound's ds_queue. At the end of each step, ctrl_sound dequeues each item to a ds_list and weeds out the duplicates (by checking if a dequeued item is already part of the list). When the queue is empty, it starts playing each sound that's in that list.
 

TrunX

Member
Thank you for the input. The suggested methods from Misty and Phil seem to do the same as my second solution with the ds_list or do I miss something?
 

Yal

🐧 *penguin noises*
GMC Elder
If you use priorities + limiting number of channels, GM handles is behind the scenes for you... and if you play sounds with randomly alternating pitches, they won't stack up as badly even if several instances get played at once.
 
Top