Game Development Community

dev|Pro Game Development Curriculum

Plain Speech Simple Example for In-Game Music inT3D

by Steve Acaster · 08/08/2010 (4:27 pm) · 7 comments

Audio. T3D audio docs are linky
Comes in main 2 types - 3D and 2D.

2D - uses both/all speakers and always plays at normal volume without distance fall-off. Should always be a stereo audio file. example: music track, ambient environmental track, etc

3D - has a distance fall-off in the level/mission area. Must be a mono audio file or it won't play. example: a fire in-game, move away from the location of the fire and the sound fades, eventually the camera is too far away to hear it at all.

You can get away with a mono track playing in 2D (stereo) but not a stereo track playing in 3D.

----------

art/datablocks/audioprofiles.cs
SFXprofile - the script for an actual sound (not required with audio emitters but we'll be using it here)
filename - audioDescription to use - preload(bool)

core/scripts/client/audiodescription.cs
SFXdescription - the script for controlling the type of sound. eg: 2D/3D, distance,etc
audioeffect (name of description and 2d or 3d)- is3D (bool) - referenceDistance (maxVolume up to this range) - MaxDistance (fade out distance) - isLooping (bool - constant play) - isStreaming(warning - crash can happen in 1.1b2 and previous builds with isLooping =true)

---------

Making a sound emitter play music in the level:
-----------------------------------------------

We are using stock stuff here, so no Fmod or mp3. read the docs for more info.

1:
First up, make sure you have an audio file. It's music we are after, so let's get a nice tune and a compatible format. I prefer .ogg because of the small size, you might want to use .wav. There are a number of apps that you can convert a wav to an ogg - I use Audacity - it's free! Make sure your music file ogg or wav is stereo.

Stick your audio file in art/sound/music - you'll have to create the "music" folder yourself.

2:
Now, open up "core/scripts/client/audiodescription.cs" and let's workaround that bug.

We could just comment out "isStreaming = true;" from "AudioMusicLoop2D" and "AudioMusicLoop3D", but instead, we'll make our own AudioDescription. You can call it whatever you want but let's go for "CustomMusicLoop2D". It's a 2D stereo sound that will always play at the same level, so make "is3D = false;", and we don't want it to stop, so "isLooping = true;".

singleton SFXDescription( CustomMusicLoop2D : AudioMusic )
{
   is3D              = false;
   isLooping         = true;
};

3:
Next for the script for the actual music file. In "art/datablocks/audioprofiles.cs" make a new SFXprofile.

Let's call this new SFXprofile "customMusic", give it the location of the file under "filename", and assign it the "description = "CustomMusicLoop2D";" that we've just made, and let's preload it so it's ready to play on start up, "preload = true;".

singleton SFXProfile(customMusic)
{
   filename = "art/sound/music/my_audio_file.ogg";//change this name to your audio file's name
   description = "CustomMusicLoop2D";
   preload = true;
};

4.
Boot up Torque3D and open you level/mission so that you are now in-game, and hit F11 to open up the world editor.
World Editor->Library->Level->Environment-> and hit "Sound Emitter". If you have object->drop location-> set to "at camera", the view will go red and black, because you have the camera stuck inside the object. back yp a little so that you can see the Sound Emitter Object.

5.
Sound Emitter settings.

The important area is "Media" which has "track" and "fileName". Hit track and a menu should appear, now find your SFXprofile (remember you called it "CustomMusic"?). It should start playing immediately but ignore it for now - everytime you make a change or un/check a box it should restart. Now we're using "track" rather than "fileName" so that we've had to go and learn how to make SFXdescriptions and SFXprofiles, but you could have avoided this ... but now you know how to do it.

We want it to play all the time, so let's make sure that the "PlayonAdd" box is checked (it should be as default).

It's music we want, so let's add it to that group. In "SourceGroup" select "AudioChannelMusic" from the drop-down menu.

Next, let's make the emitter obey it's profiles. Under "sound" select "UseTrackDescriptionOnly". This negates all the other settings in one fell stroke. This Sound Emitter now only obeys the scripts we made.

But, just to be tidy, let's enable/disable the other options anyway ...
"isLooping" - we want this. check the box (it should be as default)
"isStreaming" - NO! we don't want this. uncheck the box (it should be as default)
and a bit below ...
"is3D" - No, it isn't, it's a 2D sound, uncheck this box. The box will now turn from a bright green (3D) to a dull green (2D) to give a visual indicator of what type it is.

Let's Save our mission file and exit. Now reload it, and if everything is working correctly, music should start playing. Huzzar!

Known Issues:
There is an issue related to audio which I wanted to mention (beyond the aforementioned bug issues with streaming looped sounds) ... but I've forgotten! I'll edit it in if I remember. :P

#1
08/08/2010 (4:55 pm)
hehe Thanks very much Steve. I really appreciate it.
#2
08/10/2010 (4:00 am)
i don't have .cs file "audiodescription.cs" is it included? Kinda confused here...
#3
08/10/2010 (10:25 am)
@Edward
The Audio system has had a bit of an overhaul since 1.0.1, you'll find AudioDesrciptions.cs in core/art/datablocks.
#4
08/11/2010 (3:09 am)
thanks Steve!
#5
08/15/2010 (4:55 am)
Nice one Steve,

I have a request, could you do one in plain speech on how to add music to a main menu gui? or different screens?
#6
09/14/2010 (4:09 am)
@Donald
Since you have access to the source code Donald. If you take a look at the sfx folder in the source files. Look at the console methods related to playing, pausing, and stopping sound.

When I had to tackle issues of this nature I found that having a global playlist is very helpful.
I used
$playList::GameName[0]; Last song played
$playList::GameName[1]; Current playing song
$playList::GameName[2]; Next song

Then I just made function methods that took those objects and transitioned them.

If you are wondering how to get the object to store in a global variable keep in mind that when you call a file to be played the SFX engine returns the value of the object if one is present to recieve it.
%nextSong = sfx.play("whatEver.mp3"); //I can't remember the exact code you would have to look it up.
#7
09/21/2010 (4:41 am)
I have a very large map, with several distinct areas. To trigger ambient music which differs for different areas of your map, you can do this:

1) Create the SFXEmitter.
2) Add the file to it (or the track. I used a file, because track didn't work for me right off.
3) Make sure the SFXEmitter does not have "is3D" checked--the sound should be "flat" for music, and not angle in and out from a source point. Also, uncheck "PlayOnAdd", so that the sound does not start playing until explicitly started.
4) Create a trigger with the Library->Level->Level palette. Size it to fit the area where you would like the sound to be "heard".
5) In the field "" of the trigger, place "YourSFXEmittersName.play();"
6) In the field "" of the trigger, place "Your SFXEmitterName.stop();"

The ambient music should start to play when you enter the trigger, and stop when you exit.

Thanks, Steve!

(One further step: accept that this is undoubtedly the Wrong Way to do this, since I thought of it....)