Fade-in and fade-out AudioChannel

Started by bx83, Sun 12/03/2017 04:17:40

Previous topic - Next topic

bx83

Hi everyone

I've already picked up on how to play a tune with AudioChannel (where chan1 is a global variable *AudioChannel type):

Code: ags

chan1 = aMusic.Play();


The music keeps playing between rooms, unless I use Game.StopAudio()

But when I have different tracks for 2 rooms, How do I fade out one, and fade-in the next? I've tried the following:

Code: ags

chan1 = aMusic-1.Play(eAudioPriorityNormal, eRepeat);

if (chan1.IsPlaying==true){
  for (int x=1; chan1.Volume<=0; x++){
    chan1.Volume=chan1.Volume-1;
  }
}

chan1 = aMusic-2.Play(eAudioPriorityNormal, eRepeat);


But doesn't work.

Is this correct syntax?

Is it reducing the volume so quickly I don't even here it before the Music-2 plays?

Also: is there a function to find out what an AudioChannel* is playing, AND THE NAME of what it's playing?

Dualnames

Music channels don't work, as far as I've tried.
Only fading sounds in and out will do what you are trying to do here.

Also your first line is triggering the sound to play again on each loop. I can paste a small code that does what you want, if you want, so it's easier to explain myself.
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

Snarky

I don't think the AudioType makes a difference, Duals.

bx83, this won't work because the whole loop gets run in a single game frame, so the volume is set to 0 instantly. You either have to add a Wait() inside the loop â€" but then the game will block while fading out the music â€" or use some other method. You could adjust the volume in repeatedly_execute(), but I would recommend using the Tween module:

Code: ags
#define MUSIC_TIMER 1
AudioClip* trackToPlay;

function someFunction()
{
  // ...
  chan1 = aMusic-1.Play(eAudioPriorityNormal, eRepeat);
  // ... this next bit should probably go elsewhere, or the music will start fading out the moment it starts playing
  if (chan1.IsPlaying==true)
  {
    chan1.TweenFadeOut(1.0);    // Fades out the music over a second
    trackToPlay = aMusic-2;
    SetTimer(MUSIC_TIMER, GetGameSpeed());    // Wait a second for the next track to start
  }
  else
    aMusic-2.Play(eAudioPriorityNormal, eRepeat);
}

function repeatedly_execute()
{
  if(IsTimerExpired(MUSIC_TIMER))
  {
    trackToPlay.Play(eAudioPriorityNormal, eRepeat);
  }
}

Dualnames

If he wants to crossfade them it does.
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

Snarky

Oh, I think I see what you mean. But I don't think there is any fundamental difference between how different audio types behave â€" it's only that AGS by default has set the MaxChannels for music to 1, so you can't play more than one music track at a time. You can easily change this if necessary, however. You're right that this does mean that you can't crossfade tracks manually, though you can do so using a game setting (SetGameOption(OPT_CROSSFADEMUSIC, 1);).

We discussed and experimented with the AGS sound system quite a bit in November:

http://www.adventuregamestudio.co.uk/forums/index.php?topic=54062.0
http://www.adventuregamestudio.co.uk/forums/index.php?topic=54221.0
http://www.adventuregamestudio.co.uk/forums/index.php?topic=54209.0

Dualnames

Anyhow to not make this confusing for bx83, Snarky's post is the best answer here. If you want to crossfade do let us know.
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

bx83

I would like to crossfade, and I've spent 10hours trying to figure it out :/

Imagine, your room 1, where the game starts:

Code: ags

chan1 = global variable, audiochannel

room 1
function room_Load() {
  if (chan1==null) {        //this is the first time we've entered this first room
    play a track;           //setting volume etc. correctly
  }else{
    fadeout any track that's playing    //say, <room 2's track>
    wait 1 second
    fadein <room 1's track>
  }
}



That's it. That's all I need to do - but I've written 15 pages of code over many hours, and I can't get it. There's no howto, there's no Tween howto :(
Please, please show me how to achieve the above, with Global variable, GlobalScript definitions etc. Please :|


ps. tried your example below Snarky, and it's all good except I can't make trackToPlay a variable - not global (because god knows?), or defined in GlobalScript header (also no idea), or local (because the GlobalScript needs it). If you want to update that example, please be very specific about where these functions are.

pps. noticed that 'Sounds' and 'Music' seem to be on different channels/systems? They're the *only* examples of TweenFadeIn/TweenFadeOut that actually work.

Snarky

#7
Quote from: bx83 on Tue 14/03/2017 10:18:04
There's no howto, there's no Tween howto :(

Actually, the Tween module is extensively documented: https://ags-tween.readthedocs.io/en/v2.1.0/

Quote from: bx83 on Tue 14/03/2017 10:18:04
I would like to crossfade, and I've spent 10hours trying to figure it out :/

Quote
Code: ags

    fadeout any track that's playing    //say, <room 2's track>
    wait 1 second
    fadein <room 1's track>
  }
}


That's it. That's all I need to do

You're contradicting yourself here. Crossfading is different from what your pseudocode describes: it's fading down one track while simultaneously fading up the other, not first fading out one track and then fading in another. The easiest way to crossfade two music tracks is to set the game option to crossfade music, and then just playing the next track:

Code: ags
  SetGameOption(OPT_CROSSFADEMUSIC, 1);
  aMusic-2.Play(eAudioPriorityNormal, eRepeat);


Quoteps. tried your example below Snarky, and it's all good except I can't make trackToPlay a variable - not global (because god knows?), or defined in GlobalScript header (also no idea), or local (because the GlobalScript needs it). If you want to update that example, please be very specific about where these functions are.

If you just want it in one room you could put it all in the room code, but presumably you want to be able to call it from different rooms, so let's make it a function, switchMusic(). We'll put it in the global script (or it could be its own script module, it doesn't matter), and put an import statement in the header so that it can be seen by the room scripts.

Code: ags
//GlobalScript.ash
import void switchMusic(AudioClip* newTrack);


Code: ags
//Globalscript.asc
#define MUSIC_TIMER 1 // This is just to make the code more readable
AudioChannel* musicChannel = null; // This keeps track of which audio channel is used for music
AudioClip* musicTrackToPlay; // This keeps track of which track we're playing next, after the current one has faded out
 
void switchMusic(AudioClip* newTrack)
{
  if (musicChannel != null && musicChannel.IsPlaying)
  {
    musicChannel.TweenFadeOut(1.0);    // Fades out the music over a second
    musicTrackToPlay = newTrack;
    SetTimer(MUSIC_TIMER, GetGameSpeed());    // Wait a second for the next track to start
  }
  else
    musicChannel = newTrack.Play(eAudioPriorityNormal, eRepeat);
}
 
function repeatedly_execute() // or repeatedly_execute_always()
{
  // ... other, unrelated code may go here
  if(IsTimerExpired(MUSIC_TIMER))
  {
    if(musicChannel != null)
      musicChannel.Stop();
    musicChannel = trackToPlay.Play(eAudioPriorityNormal, eRepeat);
    musicChannel.TweenFadeIn(1.0);
  }
}


Code: ags
// roomN.asc
function room_Load()
{
  switchMusic(aMusic-2);
  // other stuff
}


Quotepps. noticed that 'Sounds' and 'Music' seem to be on different channels/systems? They're the *only* examples of TweenFadeIn/TweenFadeOut that actually work.

AGS can play up to 8 different audio clips at the same time. This is done by allocating each clip to a slot called an audio channel. To help manage this, the system allows you to define different audio types: by default "Sound" and "Music" (plus one implicit one: "Speech"). That way, you can control how many channels are used for the different audio types. By default again, 1 channel is allocated to music, 1 to speech, and the rest to sound.

TweenFadeIn/Out should work with no difference for music and sounds, since they're actually dealing with audio channels, not audio types. If not, you must be doing something wrong.

bx83

Does SetGameOption have to be in room script, global script, or global header?

Thankyou btw, it's all becoming much clearer :)

Snarky

#9
These are two alternative solutions, to produce the two different things you describe.

If you use the second solution (which is to first fade out one track and then fade in the next), you don't need to (and shouldn't!) call SetGameOption() at all.

If you use the first solution (which is to crossfade the tracks: fading out one track while fading in the next), you just have to call it somewhere â€" it doesn't matter where, as long as it has been called by the time you play the second music track. Usually if I need to set some game settings that apply throughout the game, I call SetGameOption() in on_game_start() in GlobalScript. Note that this solution is much simpler, but it is not as flexible: you can only set the crossfade length to one of four preset values, for example.

Oh! Another thing: If you use the first solution, you should use switchMusic() to play the first track as well, because that will set the musicChannel variable so that the fading happens for the next track.

bx83

Hi all

I've figured out how to make songs cross-fade into eachother with a game setting - SetGameOption(OPT_CROSSFADEMUSIC, 2)
However, when I play a sound effect (in Sounds, as opposed to Music, in the Audio subbar), how do I get *it* to stop/crossfade with another sound effect? How can I play Music (eg. SpookyRooomSong_1) and a Sound (eg. SpookyWind), and also control if sound effects stop or start when I go to a new room?

Snarky

Since this was already discussed at length in the thread for your previous question, I've merged them.

SetGameOption() only works for music, but the other solutions described above work equally well for other audio types. If you want to actually crossfade (not first fade out one and then fade in the other) you'll have to modify the code slightly: if you understand how it works it should be easy.

bx83

I just... don't really understand it :/
Is there a crossfade option in SetGameOption that works for sound effects? Or a 'stop' command that will stop only sound effects?
I thought I understood it again, but I don't... again. -_-

Snarky

Quote from: bx83 on Wed 17/05/2017 12:37:22Is there a crossfade option in SetGameOption that works for sound effects?

No.

QuoteOr a 'stop' command that will stop only sound effects?
I thought I understood it again, but I don't... again. -_-

If you just want to stop the sound effects immediately (without cross-fading), there are a couple of ways to do that.

The simplest (but also crudest) is to just call Stop() on each sound effect audio clip that might be playing.

There isn't a built-in function that will stop all clips of a certain type

Edit: Actually there is, it just in a weird place in the manual. Game.StopAudio(optional AudioType)

Spoiler
but it's possible to make one:

Code: ags
void StopAudioType(AudioType type)
{
  int i=0;
  while(i < System.AudioChannelCount)
  {
    AudioClip* clip = System.AudioChannels[i].PlayingClip;
    if(clip != null && clip.Type == type)
      clip.Stop();
    i++;
  }
}

You would call it as StopAudioType(eAudioTypeSound);
[close]

Edit2: As for crossfading, it's not as easy as with music, because while you'll usually only have a single music track at a time, you might have any number of sound effects. And while the built-in crossfade in SetGameOption() allows you to mix two music tracks on a single audio channel, you can't do that for sound effects: for each pair of sounds you want to cross-fade, you need two audio channels. If you have any more than three sound effects going on, you won't have enough audio channels to cross-fade them all at the same time. (Because AGS only has 8 audio channels, and one is reserved for speech and one for music.) That does not apply to first fading out one track and then fading in another.

So how best to code it depends on a few things:
-How many sound effects could be playing concurrently in the room you came from?
-How many do you want to play in the room you enter as you enter it?
-Are the sound effects playing constantly on a loop, intermittently, or what?
-How long are the audio clips of the sound effects?
-What, exactly, is the effect you want to create? (E.g. crossfade or fadeout-fadein; all the sound effects fading together or one at a time, etc.)

SMF spam blocked by CleanTalk