TUTORIAL: Using FMOD for In-Game Music

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
shiftlynx
Posts: 6
Joined: May 27, 2005 18:37
Location: United Kingdom
Contact:

TUTORIAL: Using FMOD for In-Game Music

Postby shiftlynx » May 27, 2005 18:39

Image

Introduction
In this tutorial, I will show you the basics of using FMOD to play music and sound effects in your FreeBASIC programs and games. :) Plasma has done a great job in porting the FMOD headers, which are included with the FreeBASIC release, so you don't have to download anything other than FreeBASIC to get started.

Download Accompanying Tutorial Files

FMOD is an amazing sound library. Their web site is at http://www.fmod.org/. If you're writing a shareware or commercial game using the library, you'll have to dish up a lot of money for the licence (and so you should, if you're going to be getting cash from it! there is a very good discount for shareware developers, rather than commercial, by the way). For freeware games though, which you will probably be making, the licence is free to use! More information about the licences is available on the FMOD web page.

FMOD is capable of playing a vast spectrum of different formats. It can currently load and play these 'music' formats: .MID, .MOD, .S3M, .XM, .IT, .RMI, .SGT and .FSB. It can also load and play these 'static sound' file formats: .WAV, .MP2, .MP3, .OGG and .RAW.


Image


Before Starting
Before writing any programs using FMOD, you will find the FMOD documentation EXTREMELY useful. It's really easy to use as well. You can download it in .CHM format from here: http://www.cdsoft.co.uk/fbstuff/fmod.chm


Image


Initialisation
The first thing that we must do is include the relevant header file. To use FMOD's functions, we just need to add this to the top of our program:

Code: Select all

'$INCLUDE: 'fmod.bi'


The next thing that we need is to initialise the library. This is done through the FSOUND_Init function, through which you must specify the sample rate and number of channels that you want. I usually just stick with a sample rate of 48000Hz and 8 channels, which should be plenty. FSOUND_Init also takes one last parameter, through which you can specify some other options. You can look up all of these options in the FSOUND_INIT_FLAGS section of the FMOD reference.

Code: Select all

' Initialise FMOD with 48000Hz, 8 channels.
FSOUND_Init(48000, 8, 0)


Okay, great! Now we're ready to start loading the songs. If you've used FMOD before in C, you will know that to store information about a loaded song, you stored a pointer to an FMUSIC_MODULE structure. Well this isn't needed in FreeBASIC - all we need to do is store the integer, as this effectively acts as the pointer anyway. To save confusion, I will just refer to this pointer as the 'song ID'.

By the way, before exiting, our program should call FSOUND_Close. This will ensure that FMOD has time to clean up all of the memory resources it used and allows it to unload properly.

Our skeleton code is now this:

Code: Select all

'$INCLUDE: 'fmod.bi'

FSOUND_Init(48000, 8, 0)

' Main code goes here!

FSOUND_Close
END



Image


Loading and Playing Songs
In FMOD, 'songs' are considered to be either MIDI files or modular music (S3M, MOD, XM, etc.). For each song we load, we have to keep a reference to it - this is just done by keeping an integer. Using this reference, we can play the song and deallocate it nicely at the end of our program.

The function we'll be using to load the song is the FMUSIC_LoadSong function, which accepts just one argument: the file name of the song, and returns the reference ID. I will stick to loading the MIDI included in the accompanying tutorial zip archive. This MIDI is originally from Ultima Underworld 2.

Code: Select all

DIM backgroundMusic AS INTEGER

backgroundMusic = FMUSIC_LoadSong("uw2-07.mid")


To check for a loading error, you can just see if the return value is 0.

Code: Select all

IF backgroundMusic = 0 THEN
    PRINT "Error: Failed to load the MIDI file!"
    FSOUND_Close
    END
END IF


There is also a function called FMUSIC_LoadSongEx which gives you more control over the loading process. You can use this function to load the song from memory instead of from a file, or you can tell it to load the song from a specific offset in the file... if you're really interested in using this (e.g. if your game loads data from a .PAK file), read up on the function in the FMOD documentation - there are a lot of optional arguments, so it's not too hard to change your code to load from an archive or memory instead. :)


Now to play the file, it's just a simple case of calling FMUSIC_PlaySong, passing our song ID as the argument. Although there is one more little thing that we need to know. Inside our main loop, we need to call FSOUND_Update, which tells FMOD to update the sound buffers, etc. - i.e. it tells FMOD to keep playing what it's been told to do!

So now take this as an example:

Code: Select all

FMUSIC_PlaySong(backgroundMusic)
WHILE INKEY$ = ""
    FSOUND_Update
WEND


Cool stuff. But what's that? It only plays once? We can fix that using the FMUSIC_SetLooping function. The first argument is the song you want to set looping on and the second is the flag - '0' indicates that the song shouldn't loop and '1' indicates that it should:

Code: Select all

FMUSIC_SetLooping(backgroundMusic, 1)
FMUSIC_PlaySong(backgroundMusic)

WHILE INKEY$ = ""
    FSOUND_Update
WEND


How about stopping songs? You can stop each of the individual songs by using FMUSIC_StopSong, passing the song ID as the argument. Either that, or you can stop -all- of the songs playing by using FMUSIC_StopAllSongs.

Let's try it using a MOD this time (from one of my favourite MOD artists... Nightbeat :)).

Code: Select all

'$INCLUDE: 'fmod.bi'

DIM niceSong AS INTEGER

' 48kHz sample rate, 8 channels.
FSOUND_Init(48000, 8, 0)

niceSong = FMUSIC_LoadSong("CHILDRMX.S3M")
IF niceSong = 0 THEN
    PRINT "Error: Failed to load 'CHILDRMX.S3M'!"
    FSOUND_Close
    END
END IF

' make it loop.
FMUSIC_SetLooping(niceSong, 1)

' play.
FMUSIC_PlaySong(niceSong)
WHILE INKEY$ = ""
    FSOUND_Update
WEND

' stop the song and quit.
FMUSIC_StopSong(niceSong)
FSOUND_Close

END


It's so easy to do! Now you have no excuse not to have music in your games (unless you're a terrible musician and have nobody to help work with you, like me :()!

Let's review the process...
    1. Initialise FMOD
    2. Load the songs you need
    3. Write the main loop, remembering to call FSOUND_Update each cycle
    4. Unload FMOD

You can play or stop the song any time you want to throughout your main loop... so if you need to change the song each time a level changes, all you have to do is add something like this to your level changing routine:

Code: Select all

FMUSIC_StopAllSongs
FMUSIC_PlaySong(newSongID)


A couple of other useful functions:
    FMUSIC_IsPlaying - Pass the song ID and it will return 1 if the song is playing, 0 if not.
    FMUSIC_IsFinished - Pass the song ID and it will return 1 if the song has finished, 0 if not.
Image


Loading and Playing Samples
Samples are considered to be 'static sound' in FMOD... this includes .WAV, .MP2, .MP3, .OGG and .RAW files. The process is very similar to loading and playing songs - there is one advantage though, we don't have to explicitly deallocate the samples ourselves at the end of the program. The FMOD developers realised that this can be a bit of a pain if you're using hundreds of samples in a large game, so they decided to add this automanager for you. There is a way to tell FMOD not to manage the samples for you if you really want - have a look in the reference manual at the FSOUND_Sample_Load function.

Speaking of which, the next function we'll be using is FSOUND_Sample_Load. As you can guess, it loads a sample from a file. This function returns a sample ID, just like the FMUSIC_LoadSong function did. We can use this ID to refer to the sample when playing it.

The FSOUND_Sample_Load function takes a few more arguments than the FMUSIC_LoadSong function though:
    index The first argument is the 'index'. If you want, you can tell FMOD to use a specific index in its internal list of samples... but that doesn't sound too flexible to me, so we'll tell it to use the next free sample slot. We do this by passing FSOUND_FREE as the 'index' argument.

    name_or_data - The file name to load from (or if you're loading from memory, the offset in memory to load from).

    inputmode - Allows you to specify some optional modes. Leave this as 0 if you're loading from a file for FMOD to figure everything out automatically. If you're loading from memory, pass FSOUND_LOADMEMORY as the value for this argument. If you want to know more about what this argument can be, look up FSOUND_MODES in the FMOD manual.

    offset - If you're loading the sample from a normal file, just leave this as 0. If you're loading it from an archived file, like a .PAK file, set this as the offset within in file you specified as 'name_or_data' where the sample is located.

    length - If loading from a file, leave this as 0. If loading from memory, specify the length of the buffer pointed to by 'name_or_data'.

Okay, so it's not really that bad! Here is the code for loading an MP3.

Code: Select all

DIM mySample AS INTEGER

mySample = FSOUND_Sample_Load(FSOUND_FREE, "HC-MainTitle.mp3", 0, 0, 0)
IF mySample = 0 THEN
    PRINT "Error: Failed to load the sample!"
    FSOUND_Close
    END
END IF


Playing is extremely simple. All we have to use is the FSOUND_PlaySound function, which accepts two arguments: the channel to play the sample in and the sample ID. If, like me, you couldn't really care about which channel the sample plays in, just set the first argument to FSOUND_FREE. FMOD will pick a free one for you. If you find that in your game, some of the sounds aren't playing, try increasing the number of channels you specify in the FMOD initialisation code.

Code: Select all

FSOUND_PlaySound(FSOUND_FREE, mySample)
WHILE INKEY$ = ""
    FSOUND_Update
WEND


Remember to call FSOUND_Update as usual.

To stop a sound playing, use FSOUND_StopSound, passing the sample ID as the argument.

If you want the sample to loop, you must set the appropriate sample mode. Do this with the FSOUND_Sample_SetMode function, which requires the sample ID and the mode to set. We'll be setting the FSOUND_LOOP_NORMAL mode (for more modes, look up FSOUND_Sample_SetMode in the FMOD documentation).

Code: Select all

FSOUND_Sample_SetMode(mySample, FSOUND_LOOP_NORMAL)
FSOUND_PlaySound(FSOUND_FREE, mySample)

WHILE INKEY$ = ""
    FSOUND_Update
WEND


So now, the full code for loading and playing a sample:

Code: Select all

'$INCLUDE: 'fmod.bi'

DIM mySample AS INTEGER

' 48kHz sample rate, 8 channels.
FSOUND_Init(48000, 8, 0)

mySample = FSOUND_Sample_Load(FSOUND_FREE, "HC-MainTitle.mp3", 0, 0, 0)
IF mySample = 0 THEN
    PRINT "Error: Failed to load the sample!"
    FSOUND_Close
    END
END IF

FSOUND_Sample_SetMode(mySample, FSOUND_LOOP_NORMAL)
FSOUND_PlaySound(FSOUND_FREE, mySample)

WHILE INKEY$ = ""
    FSOUND_Update
WEND

FSOUND_Close

END


Beautiful.


Image


Conclusion
As you can see, using FMOD is extremely simple. It is also a good idea to learn to use FMOD in your games if you're planning on trying to make commercial games in the future; you can distribute freeware while you're learning, then buy a fairly cheap shareware licence. If that takes off, then you could even go for a commercial licence. The licencing has been well designed so that you can hop up to each stage like that.

If anything, you should use FMOD because it's free, it's well-written and it's really, really easy to use. :)

I hope this inspired at least some people to use FMOD through FreeBASIC. Feedback on the tutorial would be warmly welcomed.

If you'd like to contact me, you can e-mail: c.g.davies@gmail.com
Or visit my site: http://www.cdsoft.co.uk/


-shiftLynx
cha0s
Site Admin
Posts: 5317
Joined: May 27, 2005 6:42
Location: Illinois
Contact:

Postby cha0s » May 27, 2005 21:53

nice job on this tut ;) i learned what i know about fmod from reading this. Thanks!
Chronos
Posts: 40
Joined: May 31, 2005 15:21
Location: KY, USA
Contact:

Postby Chronos » Jun 15, 2005 14:30

This tutorial is awesome. Now, once I actually learn how to develop games in FB, I'm definitely going to use this information to add music and sound to the game. :D
Frobozz
Posts: 33
Joined: Jun 12, 2005 20:32

Postby Frobozz » Jun 15, 2005 20:39

Why don't you submit this for the next edition of QBE? Although from the way the content has been going, it should probably be called FreeBASIC Express.
MystikShadows
Posts: 612
Joined: Jun 15, 2005 13:22
Location: Upstate NY
Contact:

Postby MystikShadows » Jun 15, 2005 20:52

Yes indeed, it's QBE material for sure :-)...great job :-)
relsoft
Posts: 1767
Joined: May 27, 2005 10:34
Location: Philippines
Contact:

Postby relsoft » Jun 16, 2005 6:16

Cool article!!!
KarLKoX
Posts: 1
Joined: Jun 19, 2005 7:56
Location: France
Contact:

Postby KarLKoX » Jun 19, 2005 8:08

Nice article ... but there are some points to clarify :

- FSOUND_Update : you only must call this when you init fmod with the FSOUND_OUTPUT_NOSOUND_NONREALTIME flag. FSOUND_Update must be called whenever you want to update the sound (for cycle timing for example), commenting out FSOUND_Update will not break the playback (FMOD update by itself it's mixer because you don't use the FSOUND_OUTPUT_NOSOUND_NONREALTIME flag),

- FSOUND_SAMPLE : because they are all loaded in memory (and decompressed to pcm data for compress files like mp3/ogg), you must use them with care. If you are coding a video game then there are no problem but when you are coding a player, FSOUND_STREAM is recommended : files are streamly read, performance will be better than fitting the file in memory (again, for a player).

- It is recommended to init FMOD with 32 channels with modules (even for protracker .mod because some of them can handle 32 channels)

- Finally, this is a detail but for sound performance, setting the sampling rate to the native dsp sampling rate of the soundcard is recommended (the dsp will not resample if the data sent is in the native format)
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Jul 25, 2007 20:15

This looks really neat. I might take a look at this and modify it later on. Just started studying the pages over at MIT though (awesome!), so it might take a while.
TbbW
Posts: 348
Joined: Aug 19, 2005 10:08
Contact:

Postby TbbW » Jul 26, 2007 11:22

just alil heads up when it comes with fmod:
http://www.fmod.org/ifmodlicense.html

if you ever go comersial with you'r product then be prepaired to coff up $3,000 USD and if you go cross platform then it's $1,500 per extra platform.

shareware apps are $100 USD.

freeware then it is for free.

BassMod got simular fees exept in euros.
D.J.Peters
Posts: 8176
Joined: May 28, 2005 3:28
Contact:

Postby D.J.Peters » Jul 26, 2007 11:49

fbsound is sexy open source and total free :-)
(i wish i would be free too but i'm a cpuslave)
Lachie Dazdarian
Posts: 2338
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Postby Lachie Dazdarian » Jul 26, 2007 20:16

A nice tutorial. Surprised too you didn't submit it to QBE first. I hope you are not one of those who are anal about the magazine name.

I too wanted to write a tutorial on FMOD, dummy level. I am using in my projects FMOD subroutines/functions from HienTau's Visna's End which are great, and which I modified to some extent. I still might do the tutorial. My methods are slightly different.

I agree on KarLKoX about streaming music track. Really good for the user.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Jul 30, 2007 3:36

Can anyone access the tutorial download? ^.^;; I can't. Can't find the IP to check if the site's even still up! I got to finally making this .17+ compatible, but of course it wasn't much code to change. The entire tutorial download probably contains more that I should update.

Any help or download link (or ip if the site's still up) is appreciated,
I'm switching to OpenDNS again within a few days,
Thanks,
anonymous1337
Imortis
Moderator
Posts: 1729
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Postby Imortis » Jul 30, 2007 15:06

Download FMOD Tutorial.zip

You can download it here. I had it from a long time ago. Enjoy.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Jul 31, 2007 3:05

Download FMOD Tutorial .18 compatible

Yup . . . Just had to change a few lines :-)
Misthema
Posts: 2
Joined: Sep 02, 2007 21:12
Contact:

Postby Misthema » Sep 02, 2007 21:16

Great tut! Altough, can u make tutorial for FMOD's spectrums?? I really want to know, how can I get displayed FMOD System DSP Unit!
Last edited by Misthema on Sep 05, 2007 1:30, edited 1 time in total.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 2 guests