Monitoring audio volume based on sound type

Started by Gal Shemesh, Thu 24/08/2023 17:41:36

Previous topic - Next topic

Gal Shemesh

Here's the thing:

When debugging my game, I wish to keep track on the volume when my music, ambience and sound effects are playing. For this, I have to also keep track on which AudioChannel* variable type I set for playing them. So I've created 3 global variables of the AudioChannel* type for this purpose, for setting to play my sounds, as follows:

- globalChannelMusic
- globalChannelAmbiance
- globalChannelSFX

In my debugging GUI, I've created 3 labels to represent their Volume, as follows:

- lblMusVol
- lblAmbVol
- lblSFXVol

In my 'repeatedly_execute_always()' function in my Global Script, I've wrote this code:

Code: ags
if (Game.IsAudioPlaying(eAudioTypeMusic))
  {
    lblMusVol.Text = String.Format("Music Volume: %d", globalChannelMusic.Volume);
  }
  else
  {
    lblMusVol.Text = String.Format("Music Volume: 0");
  }
  if (Game.IsAudioPlaying(eAudioTypeAmbientSound))
  {
    lblAmbVol.Text = String.Format("Ambiance Volume: %d", globalChannelAmbiance.Volume);
  }
  else
  {
    lblAmbVol.Text = String.Format("Ambiance Volume: 0");
  }
  if (Game.IsAudioPlaying(eAudioTypeSFX))
  {
    lblSFXVol.Text = String.Format("SFX Volume: %d", globalChannelSFX.Volume);
  }
  else
  {
    lblSFXVol.Text = String.Format("SFX Volume: 0");
  }

Now, I'm not sure what happened, but in the first room that a sound effect is playing on a specific frame, the label changes to show its 100% volume without any problem.

In another room, I've did the very same thing (copied and pasted the code) and set it to play a different SFX. However, immediately when the sound effect is playing, it gives me the 'Error running function 'repeatedly_execute_always': Error (line 38): Null pointer referenced'.

I really don't know what happened and how come that it works in previous rooms and in the new room that I'm working on now it doesn't. I've checked the imported sound effect asset and it is set like the others as a SFX type. What am I doing wrong?

Thanks

EDIT:
I've found that if I run the game from the very beginning, the game does not crash. But if I set my player character to start in the current room I'm working on to test it from there, it crashes when the SFX is playing...
Gal Shemesh,
goldeng

Crimson Wizard

#1
Don't test for Game.IsAudioPlaying, test for the channel variable to be not null, that would be logically correct, as some sound type playing is not logically equivalent to your pointer having an assigned value.

After this the question would be, how comes a sound is playing but channel is not assigned. To find that out we'd need to know how do you start the sounds, and how do you assign these pointer variables.

Gal Shemesh

Thanks for the prompt reply, CW. Here's what I did so far:

For playing music, I wrote this under 'room_Load()':

Code: ags
globalChannelMusic = aMain_Menu.Play(eAudioPriorityNormal, eRepeat);

For playing ambience sound, I wrote this under 'room_Load()':

Code: ags
globalChannelAmbiance = aWind.Play(eAudioPriorityNormal, eOnce);

For playing sound effects - which up to this point in the game I'm buliding is during the introduction cut-scenes - I'm using this custom function in my Global Script header for assigning sounds that I've imported into AGS to specific frames:

Code: ags
void playAudioClipOnFrame(this Object*, int loop, int frame, AudioClip* sound)
{
  ViewFrame* vf = Game.GetViewFrame(this.View, loop, frame);
  vf.LinkedAudio = sound;
}

And under 'room_RepExec()' I'm setting the sounds to the frames, for example like so:
Code: ags
oEgyptRun1.playAudioClipOnFrame(0, 126, aGUNSHOT1); // first gun shot
oEgyptRun1.playAudioClipOnFrame(0, 149, aGUNSHOT2); // second gun shot
Gal Shemesh,
goldeng

Crimson Wizard

Well, it appears that globalChannelSFX pointer is never going to be assigned to anything. At least not when view frame sounds are played.

Unless you assign it somewhere else in your code?

Gal Shemesh

#4
Yes, I thought so too - but the SFX label goes from 0 to 100% when a SFX that I set in a given frame is playing... So globalChannelSFX does change from null - that what I expected to happen as I've set my SFX assets in advanced as 'SFX' type, and it appears like this is what makes it work; I've just tried changing the SFX to be of another type to see if there's a difference, and yes - the other type now changes from being null to represent the values.

The thing that drives me crazy is that the debugging labels work only if I test my game from the the 'main menu' room. If I set my player character to start in a higher room number, which does have sound effects going on in it, the SFX label don't update. By checking the code of the main menu room I don't see anything special that makes it work only when launching the game from that particular room. I'm really clueless...

EDIT:
Ok. Figured why it worked only when launching from the main menu - the main menu 'new game' button has a click sound of the SFX type that I set to play using 'globalChannelSFX = aClick.Play();' -- that what made the globalChannelSFX to change from being null, and so the next rooms sound effects also affected the SFX label to show their volume when they're play.
Gal Shemesh,
goldeng

Crimson Wizard

#5
Quote from: Gal Shemesh on Thu 24/08/2023 21:48:19Yes, I thought so too - but the SFX label goes from 0 to 100% when a SFX that I set in a given frame is playing... So globalChannelSFX does change from null - that what I expected to happen as I've set my SFX assets in advanced as 'SFX' type, and it appears like this is what makes it work

This makes no sense, globalChannelSFX is a name of a variable and it has no connection to the name of the audio type. You could call your variable "abc", that would not have any impact on what is happening.
Your script variables don't get set automatically by the engine, unless you explicitly assign them to something in script.

Quote from: Gal Shemesh on Thu 24/08/2023 21:48:19The thing that drives me crazy is that the debugging labels work only if I test my game from the the 'main menu' room.

Do you assign globalChannelSFX  to something in the main menu room script perhaps? Or in some global functions that gets called from main menu room?

Gal Shemesh

#6
QuoteDo you assign globalChannelSFX  to something in the main menu room script perhaps?
Yes, just edited my previous post. There was a click of a button that is set using the globalChannelSFX. Thanks!!

I've just set a sound asset to play on all the globalChannel variables that I made when the game starts, which changes them all from being 'null'. Now at least the game doesn't crash on me. So I'll probably make a short silent sound file for this purpose. Thing is, when a SFX is playing the labels of both the SFX and Ambience go to 100% from some reason, while only the SFX label should do so.

My current code state is after following your suggestion above, set to check for my 'global channel' variables instead of the 'Game.IsAudioPlaying'. I'm not sure why, but when I change it back to check for the 'Game.IsAudioPlaying' of each type, each label now works for what it meant to check. Though, I'm trying to figure out why the labels of both Ambience and SFX are affected when only a SFX is playing when the checks are set to check the 'global channel' variables, as you recommend to do it this way.

Gal Shemesh,
goldeng

Crimson Wizard

#7
I suspect this may be because of misunderstanding of how channels work in AGS. This is a common problem...

AGS has a fixed total number of channels, and each audio type may reserve a number of them, or don't reserve any in which case it will use any of the free ones.

If you go to your Audio Types, and look for "MaxChannels" setting - that's the number of reserved channels. if it's 0, then the sound may play on any of the free channels remaining after counting out all the reserved for other types.

When you assign your AudioChannel pointer to the result of Clip.Play, you receive a reference to channel where this particular instance of a clip played right now. But this does not guarantee you that other clips will play on the same channel, unless you restrict their audio type to only 1 channel.

Gal Shemesh

#8
Thanks for the explanation. I actually did set all my audio types in the editor to 1, to make sure that new sounds that I play on a given 'globalChannel' variable will play on the same channel as the previous. But, does it means that there will be 1 channel preserved for each type, meaning a total of 3 (Ambient, Music, SFX)? Or that there will be 1 channel in general for everything?

EDIT:
Ended up making 3 silent audio files of 1 second each (empty audio file makes AGS crash). I then set them as follows when the game starts:
Code: ags
function game_start()
{
 globalChannelAmbiance = aSilent_Ambiance.Play(eAudioPriorityNormal, eOnce);
 globalChannelMusic = aSilent_Music.Play(eAudioPriorityNormal, eOnce);
 globalChannelSFX = aSilent_SFX.Play(eAudioPriorityNormal, eOnce);
}
Now each 'globalChannel' variable is preserved for sound assets of its type.
Gal Shemesh,
goldeng

SMF spam blocked by CleanTalk