Wintermute Engine > Scripts, plugins, utilities, goodies

How to crossfade two music files

(1/3) > >>

Jerrot:
Hiya!

Now - here is my first snippet. The goal was a smooth crossfade to a new music file when jumping to the next scene.

First I had to create an entity for the music files. Actually I used two entities, but they are using the same file.

There should be a "SOUNDPANNING=FALSE" in it, but for some weird reason it crashes currently. So I chosed the position to center the entity on a 800x600 game screen. Anyway I hope this bug to be corrected soon, I'm not sure if this is a bug of my script or of WME. I will correct and edit this article as soon as I know it better. ;)

music\music.entity :


--- Code: ---ENTITY {
  NAME="music"
  CAPTION=""
  ACTIVE=TRUE
  X=400
  Y=300
  SCALABLE=FALSE
  INTERACTIVE=FALSE
  COLORABLE=FALSE
}
--- End code ---

Notice that I didn't load any soundfile yet.

In the Game.script I added two lines before changing to the scene to load the entities:


--- Code: ---global music1 = Game.LoadEntity("music\music.entity");
global music2 = Game.LoadEntity("music\music.entity");

--- End code ---


Ok. Now we jump into our scene. I wanted this scene to play "music\my_music_file.ogg" when entering.

I added these lines to the scene_init.script:


--- Code: ---#include "scripts\func_music.inc"

PlayMusicX("music\my_music_file.ogg");
--- End code ---

That's it ? YES! Well ok, of course there is the included function:

scripts\func_music.inc:


--- Code: ---// Music functions v0.2 (Jerrot, 2003-06-07)

global music1;
global music2;

function PlayMusicX(musicfile)
{
  //---------------------------------------------------------------------
  // Starts to play a musicfile. Uses a fading/crossover if another music
  // is already playing.
  //
  // Syntax:  PlayMusicX(musicfile)
  // Sample:  PlayMusicX("music\wintermutesong.ogg");
  //---------------------------------------------------------------------
     
  var old_channel, new_channel, counter;

  // when entering a scene, we don't know, which channel entity is
  // playing currently. so we have to check this here:

  if (music1.IsSoundPlaying())
  {
    old_channel = music1;
    new_channel = music2;
  }
  else if (music2.IsSoundPlaying())
  {
    old_channel = music2;
    new_channel = music1;
  }
  else
  {
    // in case no music was playing (e.g. when starting the game) we just have
    // to load the sound file into our channel entity and leave the function.

    new_channel = music1;
    new_channel.SetSoundVolume(100);
    new_channel.PlaySound(musicfile,true);
    return;
  }
 
  // this is a very simple crossover. counting to 100, the volume of the old_channel
  // is decreased to zero, while the volume of the new_channel is increased to 100.
  // the Sleep(50) command sets the speed of the crossfading.

  new_channel.SetSoundVolume(0);
  new_channel.PlaySound(musicfile,true);
  for(counter=1; counter<=100; counter=counter+1)
  {
    old_channel.SetSoundVolume(100-counter);
    new_channel.SetSoundVolume(counter);
    Sleep(50);
  }
  old_channel.StopSound();

  // That's it! Enjoy!
 
  return;
}

--- End code ---

Mnemonic:
Cool, man! Works like a charm.
May I have a small suggestion? If you put the entity loading code into this function, you won't have to modify game.script at all:

--- Code: ---function PlayMusicX(musicfile)
{
  global music1;
  global music2;
  if(music1==null) music1 = Game.LoadEntity("music\music.entity");
  if(music2==null) music2 = Game.LoadEntity("music\music.entity");
  ...

--- End code ---



--- Quote from: Jerrot on June 07, 2003, 12:32:45 AM ---There should be a "SOUNDPANNING=FALSE" in it, but for some weird reason it crashes currently.
--- End quote ---

It's "SOUND_PANNING". It shoudn't crash, though...

odnorf:
Thanks Jerrot for the great script!
May I make another suggestion?
I think that it could work with a GlobalMusicVolume too.


--- Code: ---global music1;
global music2;

// Get the global music volume
global MusicVolume = Game.GetGlobalMusicVolume

function PlayMusicX(musicfile)
{
  //---------------------------------------------------------------------
  // Starts to play a musicfile. Uses a fading/crossover if another music
  // is already playing.
  //
  // Syntax:  PlayMusicX(musicfile)
  // Sample:  PlayMusicX("music\wintermutesong.ogg");
  //---------------------------------------------------------------------
     
  var old_channel, new_channel, counter;

  // when entering a scene, we don't know, which channel entity is
  // playing currently. so we have to check this here:

  if (music1.IsSoundPlaying())
  {
    old_channel = music1;
    new_channel = music2;
  }
  else if (music2.IsSoundPlaying())
  {
    old_channel = music2;
    new_channel = music1;
  }
  else
  {
    // in case no music was playing (e.g. when starting the game) we just have
    // to load the sound file into our channel entity and leave the function.

    new_channel = music1;
    new_channel.SetSoundVolume(MusicVolume);
    new_channel.PlaySound(musicfile,true);
    return;
  }
 
  // this is a very simple crossover. counting to "MusicVolume", the volume of the old_channel
  // is decreased to zero, while the volume of the new_channel is increased to "MusicVolume".
  // the Sleep(50) command sets the speed of the crossfading.

  new_channel.SetSoundVolume(0);
  new_channel.PlaySound(musicfile,true);
  for(counter=1; counter<=MusicVolume; counter=counter+1)
  {
    old_channel.SetSoundVolume(MusicVolume-counter);
    new_channel.SetSoundVolume(counter);
    Sleep(50);
  }
  old_channel.StopSound();

  // That's it! Enjoy!
 
  return;
}

--- End code ---

Ofcouse the game that is going to use this script must have a menu, so that the player can adjust the GlobalMusicVolume.
Mnemonic, does the SetGlobalMusicVolume adjusts the music volume in real time, or only after a restore? Is the volume saved in the registry or only in the saved games? The Game.GetGlobalMusicVolume reads the value from the registry or a saved game?

Mnemonic:

--- Quote from: odnorf on June 07, 2003, 10:33:17 AM ---Mnemonic, does the SetGlobalMusicVolume adjusts the music volume in real time, or only after a restore? Is the volume saved in the registry or only in the saved games? The Game.GetGlobalMusicVolume reads the value from the registry or a saved game?

--- End quote ---
Yes, SetGlobalMusicVolume works in realtime, the value is stored in registry (i.e. it's a per-user setting), and always GetGlobalMusicVolume reflects the current volume.

odnorf:

--- Quote ---Yes, SetGlobalMusicVolume works in realtime, the value is stored in registry (i.e. it's a per-user setting), and always GetGlobalMusicVolume reflects the current volume.
--- End quote ---

Does this mean that the modified Jerrot code's with the Game.GetGlobalMusicVolume works? I don't have the time to test it now.

Navigation

[0] Message Index

[#] Next page

Go to full version