Author Topic: [SOLVED] Playing an AudioClip blocking?  (Read 679 times)

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
[SOLVED] Playing an AudioClip blocking?
« on: 16 Dec 2018, 18:42 »
Is it possible to play an audio clip in a blocking manner (i.e. synchronously)? It is part of a sound related puzzle where after a certain interaction I play a sound and when the sound is finished I do something else.

If it is not possible, I guess I could either check in repEx for the playback to finish or do a while loop in the calling function and check there.
Ideally, I would be able to combine this with a cutscene i.e. player interacts with item, sound starts, player clicks or presses escape, the action afterwards is performed immediately.
« Last Edit: 05 Jan 2019, 14:00 by cat »

Re: Playing an AudioClip blocking?
« Reply #1 on: 16 Dec 2018, 20:55 »
If I understand that correctly, use the Wait(); command to block all actions after playing the sound. You might need a bit of trial and error to get the right timing when entering the number in the brackets. That's what I have been doing anyway, so I don't know if there is a better way. Sometimes I needed a character to animate and have him making say, a picking up sound, so I wouldn't use a blocking animation, instead I'd have the animation start as eNoBlock, then Wait, then play the sound, then Wait again, using the correct time I need to have the animation fully play out.

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #2 on: 17 Dec 2018, 15:00 »
Good point. Wait() should also work well with cutscenes.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #3 on: 17 Dec 2018, 15:49 »
I believe this will work?

Code: Adventure Game Studio
  1. void PlayBlocking(this AudioClip*, AudioPriority pri)
  2. {
  3.   AudioChannel* c = this.Play(pri, eOnce);
  4.   while(c.PlayingClip == this) Wait(1);
  5. }

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #4 on: 17 Dec 2018, 19:18 »
I think so, but probably not within a cutscene. AFAIK wait() will be skipped in a cutscene, but this loop can't be stopped.

Re: Playing an AudioClip blocking?
« Reply #5 on: 17 Dec 2018, 19:34 »
I think so, but probably not within a cutscene. AFAIK wait() will be skipped in a cutscene, but this loop can't be stopped.

You may try:
Code: Adventure Game Studio
  1. while(c.PlayingClip == this)
  2. {
  3.     Wait(1);
  4.     if (Game.SkippingCutscene)
  5.         c.Stop();
  6. }
  7.  

Also you need to check if Play returned null, which it also will in case cutscene skip started earlier, I think.
« Last Edit: 17 Dec 2018, 19:36 by Crimson Wizard »

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #6 on: 17 Dec 2018, 19:40 »
Interesting, thanks!

Re: Playing an AudioClip blocking?
« Reply #7 on: 17 Dec 2018, 19:48 »
If looking for a more generic solution, I think you should be careful of blocking against an AudioChannel without any checks on it (it might get something else played on it unless you are sure nothing else could hijack it with a high priority, or just use it directly). Depending on the format and how you want to handle playback stopping early, it might be safer to read the duration immediately after playback starts (incorporating a null check for people who have the audio turned off) and then block against the duration instead of the actual playback.

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #8 on: 17 Dec 2018, 20:29 »
Also very interesting! Though, I checked the documentation of AudioChannel.LengthMs:
"This is supported by all file types, but with MIDI music it is only accurate to the nearest second."

I am playing rather short MIDI files, so this will not be accurate enough. Maybe I'll have some time later to convert them to ogg, but I'm working to a deadline with MAGS.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #9 on: 17 Dec 2018, 22:05 »
If looking for a more generic solution, I think you should be careful of blocking against an AudioChannel without any checks on it (it might get something else played on it unless you are sure nothing else could hijack it with a high priority, or just use it directly). Depending on the format and how you want to handle playback stopping early, it might be safer to read the duration immediately after playback starts (incorporating a null check for people who have the audio turned off) and then block against the duration instead of the actual playback.

Since we're checking whether it's playing that particular clip, I don't see how those things would be a concern. The only case would be if the clip is interrupted by another copy of the same clip, which seems like the kind of edge case where you should just say "don't do that".

Re: Playing an AudioClip blocking?
« Reply #10 on: 17 Dec 2018, 23:51 »
Depends what you are syncing the audio with, I mean that the loop can potentially end early as well as never end.
I did preface this with "generic solution" (for people searching for how to implement this in their game) because this has edge cases, as well as a missing null check on the channel.

Snarky

  • Global Moderator
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #11 on: 18 Dec 2018, 18:18 »
There should be a null check, you're right, but otherwise I think the other edge cases are "works as designed". If the point is to block for as long as that clip is playing, then exiting early if the clip is interrupted is correct, and not exiting for as long as the clip plays is arguably correct.

The right solution here really does depend on the specific requirements, though. The fact that turning off or failing to initialize sound will bypass the blocking entirely may very well not be desired behavior in many situations. If you want to block deterministically for a specific duration that matches the normal duration of the clip exactly (even for MIDI clips), there's no way to do that other than manually syncing a Wait() with the clip length, AFAIK.

Re: Playing an AudioClip blocking?
« Reply #12 on: 20 Dec 2018, 20:19 »
..there's no way to do that other than manually syncing a Wait() with the clip length, AFAIK.

Its like we came full circle to my first post! :)

cat

  • Mittens Baronet
    • cat worked on one or more games that won an AGS Award!
    •  
    • cat worked on one or more games that was nominated for an AGS Award!
Re: Playing an AudioClip blocking?
« Reply #13 on: 23 Dec 2018, 11:00 »
So, for posterity, this is what I'm using and it works great, also regarding cutscenes:

Code: Adventure Game Studio
  1. void PlayBlocking(this AudioClip*, AudioPriority prio)
  2. {
  3.    AudioChannel* c = this.Play(prio, eOnce);
  4.  
  5.    if (c)
  6.    {
  7.       while(c.PlayingClip == this)
  8.       {
  9.           Wait(1);
  10.           if (Game.SkippingCutscene)
  11.           {
  12.               c.Stop();
  13.           }
  14.       }
  15.    }
  16. }

Thanks, guys!