Making all audio lower its volume except for one

Kyon

Member
Hi all,
I want to make a sort of "audio zoom-in"-system. In which I can "zoom in" on certain audio sources.
How I want this is that basically all other sounds, except the one I'm on now fade a bit in volume, so the one I'm on stands out.
But I just can't wrap my head around how I would go and make something like that..
Anyone can push me in the right direction?


thanks!!
kyon
 

DaveInDev

Member
in the manual, search for "audio groups" and "audio_group_set_gain", that's probably what you're looking for, except if these zoomed-in sounds are always changing... (then you'll have to handle this manually, browsing every sound and setting the gain individually).
 

Alice

Darts addict
Forum Staff
Moderator
Keep in mind that audio_sound_play return the ID of the sound instance, and then you can operate on that individual sound being played.

So if you have audio source creating the sound instance like that:
GML:
played_sound = audio_sound_play(snd_some_sound, 0, false);
audio_sound_gain(played_sound, 0.5, 0); // make the played sound more silent immediately, until zoomed in
Then you can do the following when audio source is zoomed in on:
GML:
audio_sound_gain(played_sound, 1, 500);
And make it silent again when it's zoomed out of:
GML:
audio_sound_gain(played_sound, 0.5, 500);
I hope you can figure out the rest from that. ^^
 

Kyon

Member
Ok so sorry for the late reply, but am working on this again now.
Thanks for your comments!

Yeah I was afraid it would be like that.
Having to go through every audio separately, lower them, and not lower the one I'm on.
Seems almost like an impossible task if I'm planning to have a lot of audio sources..

If anyone has another idea I would love to hear it!
 

Tyg

Member
Instead of thinking how am i going to adjust the sounds
How about using vars to set the gain instead of hard coded numbers
and have the object set its sound by proximity
you can use distance functions to set the vars automatically
can even make a parent object for this and all sounds will behave this way
can even make zones, like if _point_in_circle for a radius and set an activated flag
then it doesnt matter how many sounds there are any child of the object ..well you get it
 
Last edited:

NightFrost

Member
It doesn't come across well from your explanation, but if you are wanting to create an audio experience based on locations and moving amongst them, GMS has audio emitters and listeners. Emitters are set to play sounds at given coordinates and listeners combine these to an experience based on emitter distances from listener coordinates.
 

Kyon

Member
Just add the tag to them and loop through them ignoring the one you're on.
This could work, although I'm thinking you need audio-ID's if you want to go audio specific. (like Alice explained above)
Any thoughts on that?

Instead of thinking how am i going to adjust the sounds
How about using vars to set the gain instead of hard coded numbers
and have the object set its sound by proximity
you can use distance functions to set the vars automatically
can even make a parent object for this and all sounds will behave this way
can even make zones, like if _point_in_circle for a radius and set an activated flag
then it doesnt matter how many sounds there are any child of the object ..well you get it
Hm not sure if I understand.
Isn't this basically the same as having an audio listener and placing specific audio points?
What I try to achieve is within that world of 3D audio, make it so that you "zoom in" on specific audio sources.

Example:
You're at a crowd of people, these are a few crowd-audio sources. The moment you start to talk to the NPC that's within the crowd, all audio gets lowered in volume, except of the NPC's voiceacting.

It doesn't come across well from your explanation, but if you are wanting to create an audio experience based on locations and moving amongst them, GMS has audio emitters and listeners. Emitters are set to play sounds at given coordinates and listeners combine these to an experience based on emitter distances from listener coordinates.
Ah yes, so see what I wrote above to Tyg,
I want that within this world, you can focus on specific audios. Like a "zoom-in" effect. So if you have a few different audio sources, but choose to listen to one of them, the others fade out a bit.



One Idea I'm having is doing all audio percentage based.
Like right now I already have a few audio groups, and you can set the gain for them in the pause menu.
Maybe every time you zoom in on an audio group, the audio volume of all audio groups will go to 30% of their initial percentage, except for the audio you want to be "zoomed in" on?
 

NightFrost

Member
I want that within this world, you can focus on specific audios. Like a "zoom-in" effect. So if you have a few different audio sources, but choose to listen to one of them, the others fade out a bit.
I think this would be possible if you play around with the audio falloff model settings. When you focus on a specific group, the listener gets moved to that group's location. The model would have been tuned to give maximum gain at zero distance, while everything beyond certain distance gets the smallest gain of the model (but above zero). You could even have the listener actually move instead of just jump, so you get gradual change in volume. You'll have to play around with the models and their numbers until you get to something that fits your relative distances.
 
  • Like
Reactions: Tyg

Tyg

Member
ok, i see what you mean
how are you zooming in on the audio source
if its the mouse over, then you can use that to activate it
Sounds cool, like a crowd of people and you can hear what each one says
I just played a game called heavy rain where you had to go through a crowded train station
and each person said something different as you approached them
thats why i was asking how are you zooming in on the audio source
because if it is user selected or the npcs proximity then you would want to think about how to implement it
 
Last edited:
I know this may sound weird, but you can duplicate the sound you want to increase, but it has to be at a loop's point (Start)
Here is an example001.png002.png

I hope you find this useful! :)
 

Alice

Darts addict
Forum Staff
Moderator
As long as each audio source is associated with a specific GM object - and there is no other parent/child hierarchy involved - you can make par_AudioSource (or however else you would call that object) that would store its own sound instance.

Then, this parent could have something like this in Create event:
GML:
// how zoomed is audio right now
zoom_factor = 0;

// the lower the zoom_factor_max, the faster the sound switches from zoomed and non-zoomed volume
zoom_factor_max = 30;

// you can change this variable per audio source to get a more fine-tuned control over target volumes
audio_volume_zoomed = 1;

// this variable controls how silent the sound becomes when nonzoomed, relative to zoomed; probably should stay consistent between audio sources
audio_volume_nonzoomed_fraction = 0.3; // value of 0.3 means that nonzoomed audio will play at 30% volume of zoomed volume

played_sound = undefined; // or audio_play_sound(sound_resource, 0, false) if we define sound_resource in Object Variables
This User Defined Event 0 (or whatever number you assign, or maybe it'll be a function) would change played sound volume based on current zoom:
GML:
if (is_undefined(played_sound))
    exit; // if no sound is playing, there's no need to change volume

var zoom_fraction = zoom_factor / zoom_factor_max;
var volume_fraction = lerp(audio_volume_nonzoomed_fraction, 1, zoom_fraction);
var new_volume = volume_fraction * audio_volume_zoomed;
audio_sound_gain(played_sound, new_volume, 0);
Whenever we want specific audio source to play a specific sound, this code would be executed by audio source (you might want to wrap it in a function or something):
GML:
played_sound = audio_play_sound(/*insert sound here*/, 0, false); // or true if sound is looped
// you might also want to adjust audio_volume_zoomed here, if needed

// then adjust the volume of the newly played sound
event_user(0);
Whenever the player chooses to zoom on specific audio source (this is not necessarily called from par_AudioSource, but it affects audio source instances):
GML:
global.zoomed_audio_source = /* id of zoomed par_AudioSource instance, or noone if no audio source is zoomed */;
// it may be a non-global variable, the point is to store the currently zoomed source somewhere
Then, in End Step:
GML:
var is_zoomed = global.zoomed_audio_source == id;
if (is_zoomed && zoom_factor < zoom_factor_max) {
    zoom_factor += 1;
    event_user(0); // zoom factor changed, adjust volume
} else if (!is_zoomed && zoom_factor > 0) {
    zoom_factor -= 1;
    event_user(0); // same as above
}
Once all audio source objects inherit from such audio source parent (and correctly inherit Created/User Defined Event 0/End Step events), the only problem that remains is:
- choosing which sounds and when to play from specific audio source instances (and maybe adjusting the audio_volume_zoomed)
- switching between zoomed audio sources

No need to iterate through audio sources, let alone having to re-implement zooming volume mechanic for each audio source - just let each audio source adjust its volume in inherited End Step event. And you'll need to imlpement playing specific sounds from audio sources or switching between zoomed audio sources regardless of how the zooming itself becomes.
 
Top