MODULE: Pause and Resume all Audio

Started by Laura Hunt, Mon 22/02/2021 20:46:42

Previous topic - Next topic

Laura Hunt

Baffled by the lack of a "pause audio" function in AGS and the lack of any modules addressing this (as far as I know), I've decided to make a very simple module that provides pause and resume functionality for all currently playing audio, for example in case you want to pause everything that's playing when your Options/Pause menu comes up, and maybe play a different music piece while the menu is up, or whatever.

You can download it from here.

Usage is extremely simple, just use PauseAudio() to pause and ResumeAudio() to resume.

The only catch is that you need to set AudioPriority and RepeatStyle for each clip in the editor. So if for example you have a clip that you sometimes want to play looped and sometimes as a one-off, you'll need to import two copies of the same clip and set different attributes for each instance. Same if you want to change the priority of an audio clip.

I'm working on a more "robust" version that can actually store AudioPriority and RepeatStyle, for which you can find the (untested) code below, BUT the trade-off in this case would be that in order to play audio, you would have to use an extender function, CustomPlay, rather than the built-in Play function. Feel free to check out the code below if you want. If I find time to test it properly and it works, I could provide another variant of the module, or replace the previous one entirely.

Thanks a lot to Crimson Wizard for his infinite patience helping me figure this out!

Spoiler


Code: ags
struct ChannelAttributes {
    int channelvolume;
    int channelpanning;
    AudioClip * channelclip;
    int channelposition;
    int channelprio;
    int channelrepeat;
    int channelspeed;
};

ChannelAttributes runningchannel[8];  // if the maximum number of channels changes in the future, this will need to be updated


We also need a global bool:

Code: ags
bool isthisframeaudio = false;


This would be the extender/wrapping function that replaces the regular Play:

Code: ags
function CustomPlay(this AudioClip*, AudioPriority prio, RepeatStyle repeat)
{
    this.Play(prio, repeat);
    for (int i = 0; i < System.AudioChannelCount; i++) {
        AudioChannel* tempchannel = System.Audiochannels[i];
        if (tempchannel != null && tempchannel.PlayingClip == this) {
            runningchannel[i].channelprio = prio;
            runningchannel[i].channelrepeat = repeat;
            runningchannel[i].channelclip = this;
        }
    }
}


Pause and resume functions proper:

Code: ags
function PauseAudio() 
{
    for (int i = 0; i < System.AudioChannelCount; i++) {
        AudioChannel* tempchannel = System.Audiochannels[i];
        if (tempchannel != null && tempchannel.IsPlaying) {
          runningchannel[i].channelvolume = tempchannel.Volume;
          runningchannel[i].channelpanning = tempchannel.Panning;
          runningchannel[i].channelposition = tempchannel.Position;
          runningchannel[i].channelspeed = tempchannel.Speed;
         // here we check if the clip that is playing is the same one we played manually; if it's not, it's frame-linked audio
          if (tempchannel.PlayingClip != runningchannel[i].channelclip) isthisframeaudio = true;
          else isthisframeaudio = false;
          runningchannel[i].channelclip = tempchannel.PlayingClip;
          tempchannel.Stop();
        }
    }
}




Code: ags
function ResumeAudio() 
{
    for (int i = 0; i < System.AudioChannelCount; i++) {
        AudioChannel* tempchannel = System.Audiochannels[i];
        if (tempchannel != null) {
          AudioClip* tempclip = runningchannel[i].channelclip;
          // if the clip playing is frame-linked audio, we use the Play command with no attributes so the AudioPriority and RepeatStyle values set in the editor are used
          if (tempclip != null) {
            if (isthisframeaudio) tempchannel = tempclip.Play();
            else tempchannel = tempclip.Play(runningchannel[i].channelprio, runningchannel[i].channelrepeat);
          }
          tempchannel.Volume = runningchannel[i].channelvolume;
          tempchannel.Panning = runningchannel[i].channelpanning;
          tempchannel.Speed = runningchannel[i].channelspeed;
          tempchannel.Seek(runningchannel[i].channelposition);
        }
    }
}


[close]

eri0o

That is something useful to have! Hey, if you have the time, place the code somewhere in GitHub, because I saw a bunch of these file storages die through the life of this forum - GitHub has been more resilient so far.

Laura Hunt

#2
I will! I simply have never used Github, so I need to find a moment to create an account, tinker around, and see how it works. But I will definitely upload it there at some point :)

SMF spam blocked by CleanTalk