Trying to fadein/fadeout music using tweening module

Started by Dave Gilbert, Wed 17/04/2013 21:16:56

Previous topic - Next topic

Dave Gilbert

This is one of those occasions I really hate the new AGS sound system. You used to just be able to play a new tune and it would automatically fadein and fadeout, but no longer. :( :-\

Anyway, enough griping!

I discovered that Edmundo's lovely tweening module can tween the volume of audio channels, WITHOUT blocking. This is ideal, since I can fadein/fadeout between music and ambient sound without stopping the action.

I have three audio channels: MusicChannel, MusicChannelb and MusicChannelActive.

How it works is I start playing music on MusicChannel, then switch over to MusicChannelb (using the tween module to fade up the volume of one while fading down the volume of the other) and then setting MusicChannelActive to the new channel. I also have a silent music clip called aSilence that I use when I want to turn off the sound.

Here's the function declaration:

Code: AGS

import function MusicChange(AudioClip*thisclip, int vol=50, int time=500,  bool repeat=true);

And here's the juicy code:

Code: AGS

function MusicChange(AudioClip*thisClip, int vol, int time, bool repeat)
{
  float ftime=IntToFloat(time);
  ftime=ftime/1000.0;
  if (MusicChannelActive.PlayingClip != thisClip) //check to see if the active channel is already playing the requested clip
  {
      if (MusicChannelActive==MusicChannel) //switch to musicChannelB
      {
        if (repeat==true) 
          MusicChannelb = thisClip.Play(eAudioPriorityVeryHigh, eRepeat);
        else 
          MusicChannelb = thisClip.Play(eAudioPriorityVeryHigh, eOnce);
        MusicChannelb.Volume=0;
        MusicChannelb.TweenVolume(ftime, vol, eLinearTween, eNoBlockTween);
        MusicChannel.TweenVolume(ftime, 0, eLinearTween, eNoBlockTween);
        MusicChannelActive=MusicChannelb;
      }
      else if (MusicChannelActive==MusicChannelb) //switch to music channel A
      {
        if (repeat==true)
          MusicChannel = thisClip.Play(eAudioPriorityVeryHigh, eRepeat);
        else
          MusicChannel = thisClip.Play(eAudioPriorityVeryHigh, eOnce);
        MusicChannel.Volume=0;
        MusicChannel.TweenVolume(ftime, vol, eLinearTween, eNoBlockTween);
        MusicChannelb.TweenVolume(ftime, 0, eLinearTween, eNoBlockTween);
        MusicChannelActive=MusicChannel;
      }
  }
}

function repeatedly_execute_always()
{
  if (MusicChannelActive == MusicChannel && MusicChannelb.Volume==0) 
    MusicChannelb.Stop();
  if (MusicChannelActive == MusicChannelb && MusicChannel.Volume==0) 
    MusicChannel.Stop();
}


At game_start, everything is set to these values:

Code: AGS

  MusicChannel = aSilence.Play(eAudioPriorityNormal, eRepeat);
  MusicChannelb = aSilence.Play(eAudioPriorityNormal, eRepeat);
  MusicChannel.Volume=100;
  MusicChannelb.Volume=0;
  MusicChannelActive=MusicChannel;


The result of all this nonsense? It works... half the time. Half the time, the music doesn't change at all. Once in a while, the music doesn't even begin at the start of the game. It seems totally arbitrary and I have been spending ages trying to sort out why. So... help? What am I doing wrong? Or is there a much better way of doing this entirely?

Thanks in advance!

-Dave

Crimson Wizard

I apologize if all this is already known to you, but I would like to note something very important prior to anything else.

The AudioChannel* is a pointer, not persistent object. When you say "I have three channels" this should be read as "I have three references to audio channels".
What do they reference? They may reference absolutely nothing, for instance. Or same channel. Or different channels every other time.
The actual channel objects are inside the AGS, and you do not have direct access to them, you may only control how many of them are there.
You do this by setting "MaxChannels" in the sound type object (Project Tree -> Audio -> Types -> any type, e.g. Music -> MaxChannels).

So, first thing I'd like to ask: what did you set the MaxChannels to?
Also, check "Crossfade tracks" option, maybe you could use that one instead of manually crossfading music?

Then, just something that I noticed:
Code: ags

function MusicChange(AudioClip*thisClip, int vol, int time, bool repeat)
{
  float ftime=IntToFloat(time);
  ftime=ftime/1000.0;
  if (MusicChannelActive.PlayingClip != thisClip) //check to see if the active channel is already playing the requested clip

This will crash the game, if MusicChannelActive was not assigned prior to the function call. I don't know all your program logic, but I'd add "MusicChannelActive != null" check.

selmiak

I ran into the same thing and khris wrote a nice working audio fading script. It has no ease in, ease out, but it works, i hope this helps.

Crimson Wizard

Actually, I just made a quick test to see how AGS auto crossfading work. That may be my ears, or the music, but I really don't see (hear) any problems when music is changing. It sometimes act a bit weird when music starts in silence though (it plays in low volume first, then suddenly gets louder).
Unfortunately there's no way to set up precise crossfade duration in AGS (something worth of a feature request maybe).

Dave Gilbert

You know... you're right. Setting the music channel property to play a maximum of ONE piece of music at a time, and then just playing another tune does the crossfade automatically. I don't know why I never tried doing that. So much for my giant function of death. Cheers!

SMF spam blocked by CleanTalk