Wintermute Engine > Scripts, plugins, utilities, goodies
How to crossfade two music files
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