Restore the default sound volumes

Started by Sughly, Sun 09/09/2012 01:39:47

Previous topic - Next topic

Sughly

I have a loading screen that runs through all the animations of the game before the game starts (just to have them in memory), but I need to mute out the sound using Game.SetAudioTypeVolume(eAudioTypeSound, 0, eVolExistingAndFuture) since a lot of them have sounds triggered on certain frames, which I then bring back to 100 volume once the loading is complete. I was just wondering though, since this line will override any future volumes set for sound, is there any way of restoring the game to recognising the default volumes set for individual sounds again? Or is there maybe another way to temporarily mute all the sounds during the loading that won't permanently affect the volume of sounds later?

monkey0506

#1
Are you playing any background music or anything during this? If not you could simply use System.Volume:

Code: ags
System.Volume = 0;
// load animations into memory
System.Volume = 100;


Otherwise, it doesn't look like there would currently be a nice way of doing it:

Quote from: The Manual > Scripting > Multimedia functions > SetAudioTypeVolumeIf you use the eVolSetFutureDefault or eVolExistingAndFuture, then the DefaultVolume property for all audio clips of this type will be overridden. This means that any DefaultVolume set up in the editor will be lost.

If you need background music and don't want to lose the default volumes set up in the editor, you could create other audio types. You could have audio types like Sound100, Sound80, and Sound60 which would be sounds that default to 100, 80, and 60 for their volumes (respectively). Then you could do:

Code: ags
// header (*.ash)
import void SetSoundsVolume(int volume, int sound100Offset=0, int sound80Offset=0, int sound60Offset=0, ChangeVolumeType=eVolExistingAndFuture);
import void MuteSounds(ChangeVolumeType=eVolExistingAndFuture);
import void RestoreSoundsDefaultVolume(ChangeVolumeType=eVolExistingAndFuture);
import void StopSounds();

// script (*.asc)

void SetSoundsVolume(int volume, int sound100Offset, int sound80Offset, int sound60Offset, ChangeVolumeType changeType)
{
  Game.SetAudioTypeVolume(eAudioTypeSound100, volume + sound100Offset, changeType);
  Game.SetAudioTypeVolume(eAudioTypeSound80, volume + sound80Offset, changeType);
  Game.SetAudioTypeVolume(eAudioTypeSound60, volume + sound60Offset, changeType);
}

void MuteSounds(ChangeVolumeType changeType)
{
  SetSoundsVolume(0, 0, 0, 0, changeType);
}

void RestoreSoundsDefaultVolume(ChangeVolumeType changeType)
{
  SetSoundsVolume(100, 0, -20, -40, changeType);
}

void StopSounds()
{
  Game.StopAudio(eAudioTypeSound100);
  Game.StopAudio(eAudioTypeSound80);
  Game.StopAudio(eAudioTypeSound60);
}


Then, when you're preloading the animations you would do:

Code: ags
MuteSounds();
// preload animations
RestoreSoundsDefaultVolume();

Sughly

Oh wow, thanks so much! Yeah, I do have music playing during the loading screens. I can see what you're doing there though, very clever! Seriously, thanks so much. I'm not the most adept coder, so this is hugely helpful :-D

monkey0506

#3
Something else you could try would be to temporarily store the ViewFrame.LinkedAudio before the animation, unset it, run the animation, and then reset the audio. This could possibly increase the loading time, but the setup and use would be easier.

Code: ags
// loading screen...inside of the function that preloads the animations*
int view = 0;
while (view < Game.ViewCount) // iterate every view, feel free to change this to only the views you need
{
  int loop = 0;
  int loopCount = Game.GetLoopCountForView(view);
  player.LockView(view); // lock the player's view for animation
  while (loop < loopCount) // iterate every loop
  {
    int frame = 0;
    int frameCount = Game.GetFrameCountForLoop(view, loop);
    ViewFrame *frames[] = new ViewFrame[frameCount]; // temporary storage of ViewFrames, so we don't have to create the script objects twice
    AudioClip *linkedAudio[] = new AudioClip[frameCount]; // temporary storage of the ViewFrames' LinkedAudio
    while (frame < frameCount) // iterate every frame, storing the LinkedAudio
    {
      frames[frame] = Game.GetViewFrame(view, loop, frame); // grab each ViewFrame
      linkedAudio[frame] = frames[frame].LinkedAudio; // store its LinkedAudio so that it's not lost
      frames[frame].LinkedAudio = null; // temporarily set the LinkedAudio to null so it won't be played
      frame++;
    }
    player.Animate(loop, 0, eOnce, eBlock); // animate the player with this loop, delay 0, once, and blocking
    frame = 0;
    while (frame < frameCount) // iterate the frames again, restoring the LinkedAudio
    {
      frames[frame].LinkedAudio = linkedAudio[frame]; // restore the audio
      frames[frame] = null; // setting these to null just makes sure AGS' garbage collection picks them up...which really it would do anyway :P
      linkedAudio[frame] = null;
      frame++;
    }
    frames = null; // garbage collection for the dynamic arrays
    linkedAudio = null;
    loop++;
  }
  player.UnlockView(); // unlock the player's view
  view++;
}


*NOTE: You'll probably need to add the noloopcheck keyword to the function if you haven't already. Actually, duh, you said it's a loading screen, so you'll probably be showing a progress bar or something... You can call Wait(1) each view or every 10 views or what have you so that the screen can refresh.

This creates a significant additional overhead as you have to create the ViewFrame objects for each frame, but it would preserve the default volumes without you having to resort to using separate audio types. Note of course that this would be significantly more efficient if you specialized it to load only a certain set of animations instead of what I've done here and looping through every animation in the game.

Hopefully one of these two approaches helps you out.

Edit: You responded while I was trying to double post, argh! :) So yeah, here's another alternative. Let me know which one works for you, and you're welcome. Feels kinda good to get back to coding with AGS a bit. :)

SMF spam blocked by CleanTalk