What Is FMOD
What Is FMOD
FMOD is an easy to use crossplatform audio engine, available on the Windows, Windows CE, Linux, Macintosh, GameCube, Playstation 2 and XBox platforms. It can be used with C/C++, Visual Basic, Delphi and MASM. So, if you use one of those languages on one of these platforms and you want to use sound in your application, FMOD is made for you. The examples below will be in C although the basic principles should be the same across all platforms.
Alternatives
One alternative might be OpenAL. OpenAL is another crossplatform audio API which is available for Windows, Linux and Macintosh and can be used with C/C++, Delphi and Java. The style is similar to OpenGL (for example, the extensions technique is also used here). A Windows-specific alternative would be DirectSound which is part of Microsoft's DirectX.
Getting Started
After unpacking the archive, you should copy the FMOD.DLL into your working directory or better still, into the directory where your executable file will be. Before we can really start we have to do one last thing.
For C users
Now you only have to include the header "fmod.h" and depending on your compiler, the right import library:
fmodvc.lib for Microsoft Visual C++ and Codewarrior fmodbc.lib for Borland fmodwc.lib for Watcom fmodcc.lib for LCC-Win32 libfmod.a for MingW and CygWin fmod-3-7.lib for GCC
Initialization
Before we can use FMOD to play some sounds for us we need to initialize it. This is pretty simple: FSOUND_Init (44100, 32, 0); The first parameter is our output rate in hertz. In our example it's equal to 44100. The second parameter is our maximum number of software channels. It doesn't matter if you choose a higher number due to the fact that it won't affect your cpu usage as long as you don't really use them. However 32 should be more than enough for this short introduction.
In the third parameter can we specify some flags if we want to. We leave this parameter as 0. That's it. Now we are ready to play some sounds. But in which format do we have out sounds? Is it a song, a sample or a stream?
FMUSIC
Let's rock! To play a song you need a FMUSIC_MODULE variable for the handle and following two lines: handle=FMUSIC_LoadSong("YourFileName"); FMUSIC_PlaySong(handle); You will notice that from now on almost every function needs the handle as the first parameter.
Now, that your song is playing you can manipulate it in several ways. To make it louder you use: FMUSIC_SetMasterVolume (handle, 256); With 256 we set the volume to the maximum. If we would have passed 0 we would have have silence. To pause our song we use: FMUSIC_SetPaused (handle, true); and FMUSIC_SetPaused (handle, false); when we want to unpause it. For background music it would be nice if our music would play in an endless loop. No problem: FMUSIC_SetLooping (handle, true); And when we are tired of hearing the music we will stop it with: FMUSIC_StopSong (handle);
Cleaning Up
To free the allocated memory from a song you should simply call: FMUSIC_FreeSong (handle); and we're done. Pretty easy, isn't it?
FMUSIC_MODULE* handle;
int main () { // init FMOD sound system FSOUND_Init (44100, 32, 0);
// play song only once // when you want to play a midi file you have to disable looping // BEFORE playing the song else this command has no effect! FMUSIC_SetLooping (handle, false);
// wait until the users hits a key to end the app while (!_kbhit())
{ }
FSOUND
Due to the fact that you have more possibilities while using FSOUND it's a little bit more complicated. For instance, you have several channels which you can use simultaneously. But in this short introduction we will only be using one. First we have a look at samples, and afterwards we move on to streams.
Samples
Let's rock!
To play a sample you need a FSOUND_SAMPLE variable for the handle and following two lines: handle=FSOUND_Sample_Load (0,"YourFileName",0,0,0); FSOUND_PlaySound (0,handle); The first command loads the sample. For the beginning only the second parameter is relevant - the name of the file you want to play! The rest is important when you want to use more than one sample, play a file from memory, etc. The second command plays the actual sample. The first parameter is the channel number you want to use and the second one the handle of the sound to play. Take care that the file that you want to play is not that big! Otherwise, it will take a while until the file will be played because it is first loaded completely into memory.
Cleaning up
To unload the sample a simple FSOUND_Sample_Free (handle); is enough.
FSOUND_SAMPLE* handle;
int main () { // init FMOD sound system FSOUND_Init (44100, 32, 0);
// wait until the users hits a key to end the app while (!_kbhit()) { }
Streams
Let's rock!
To play a stream you need a FSOUND_STREAM variable for the handle and the following two lines: handle=FSOUND_Stream_Open("YourFileName",0, 0, 0); FSOUND_Stream_Play (0,handle); It's pretty much the same as samples so nothing more to say here. Note: Take care that you're using at least version 3.7. In earlier versions the command for opening a stream was different!
Cleaning up
To unload the stream a simple FSOUND_Stream_Close(handle); is enough.
FSOUND_STREAM* handle;
void main () { //init FMOD sound system FSOUND_Init (44100, 32, 0);
//wait until the users hits a key to end the app while (!_kbhit()) { }
Shutting Down
To shut down the FMOD sound system just call at the end of your program: FSOUND_Close ();
Final Words
I wrote this short article after I saw the article about OpenAL by Lee Winder at Gamedev.net. A short time later the question about how to play sound in an application came up in the forum. Even though the FMOD API comes complete with some examples and brief tutorials these might not seem as simple at the first glance. I hope this article was useful for you. For any comments, questions, feedback, etc. send me an email [email protected].
A beginner's guide to FMOD by Lachie D. (November 2007) Introduction This tutorial should introduce you with basics of using FMOD in FreeBASIC programs. It's pretty much the summary of FMOD subs and methods I use in my projects and does not represent the entire scope of FMOD in FreeBASIC. If your needs extend beyond this tutorial, you are encouraged to explore additional FMOD calls and its documentation. Originally I planed to write a cross FMOD/FBSound tutorial, but as FBSound felt rather user-unfriendly to me I gave up on that. If someone likes and prefers FBSound, be so kind to write a tutorial about it in the style of this one if you wish to popularize the library in question. What is FMOD? FMOD is a 32-bit sound library for Windows, Linux and Macintosh. It is free of charge for freeware products, but if you plan to use it in commercial products you'll have to buy a specific license. Visit www.fmod.org for more info on this. What do you need? Well, you need FreeBASIC first. I assume you have one. As the code in this tutorial was written in FreeBASIC ver.0.18 or later, get that. You also need FMOD.DLL placed in Windows/System32 directory or where you place the program source code. Get it here: http://www.fmod.org/index.php/download#FMOD3ProgrammersAPI To test the example program in this tutorial download the following sound files: fmodtutfiles.zip Initiating FMOD To use FMOD in your programs you need to include "fmod.bi" with: #include "fmod.bi" After this we'll declare several variables that will become necessary later.
CONST number_of_sound_effect = 10 CONST FALSE = 0 CONST TRUE = 1 DIM DIM DIM DIM SHARED SHARED SHARED SHARED PlaySound AS INTEGER sample(number_of_sound_effect) AS INTEGER PTR music_handle AS INTEGER PTR SFXVolume AS INTEGER, MusicVolume AS INTEGER
PlaySound will be used to flag if FMOD functions should be used or not (if FMOD initiation failed), sample array will hold the sound effects and declare it like I did. number_of_sound_effect represent the number of sound effects you'll use in your program. Change this number to suit your own needs. music_handle will flag the current music track in memory which we'll stream. I advise streaming music files instead loading all of them into memory. SFXVolume will flag the current sound effects volume, while MusicVolume the music volume. The following code initiates FMOD: PlaySound = TRUE FSOUND_Init(44100, number_of_sound_effect+1, 0) IF FSOUND_Init(44100, number_of_sound_effect+1, 0) = 0 THEN PlaySound = FALSE PlaySound is set as TRUE by default, and then it's set to FALSE if FMOD fails to initiate. The first parameter in FMOD_Init is mixrate in Hz, usually set to 44100 as most sound files have that mixrate. The second parameter is the number of SOFTWARE channels available. I added one more channel on the number of sound effects Ill use because I need one more for my music track. You can put any number here, just make sure it's more than the number of sound effects and music tracks you'll allocate at the same time in your program. Loading samples To load a sound effect use FSOUND_Sample_Load function on the following way: IF PlaySound = TRUE THEN sample(1) = FSOUND_SAMPLE_Load(FSOUND_FREE,"sound1.wav",0,0,0) sample(2) = FSOUND_SAMPLE_Load(FSOUND_FREE,"sound2.wav",0,0,0)
END IF The first parameter flags the sample slot (index). FSOUND_FREE chooses an arbitrary one. The second parameter is the name of the sound file. You can load MP3, WAV, OGG, RAW, and other file formats with this function. With the third parameter you can set the mode for that sound effect (check FMOD documentation for the description of available modes), fourth one flags the offset inside the file, and the last one flags the length of a memory block for that sound effect. Unless having special requirements, use zeros for those parameters as I did. Let's set the default music and sound effects volumes: SFXVolume = 3 MusicVolume = 3 I use 4 steps volume but you can use more. In my method 4 represents maximum volume, 3 is 75 % of maximum volume, 2 is 50 %, 1 is 25 %, and 0 is mute. To start streaming a music (or environmental) track I constructed the following subroutine: SUB playStreamMusic (musc As String) DIM SetVol AS INTEGER IF PlaySound = TRUE THEN music_handle = FSOUND_Stream_Open(musc, FSOUND_LOOP_NORMAL, 0, 0 ) FSOUND_Stream_Play(1, music_handle) IF MusicVolume = 0 THEN SetVol = 0 IF MusicVolume = 1 THEN SetVol = 63 IF MusicVolume = 2 THEN SetVol = 126 IF MusicVolume = 3 THEN SetVol = 190 IF MusicVolume = 4 THEN SetVol = 255 FSOUND_SetVolumeAbsolute(1, SetVol) END IF END SUB Be sure to declare this subroutine. To stop streaming a sound file (which is usually a music track) I use the following subroutine:
playStreamMusic ("river.ogg") FSOUND_Stream_Open opens a sound file for streaming. The first parameter flags the sound file (string), the second parameter flags the mode of streaming (how the file should be played; refer to FMOD documentation for more info on this), and the last two parameters are 0 by default and flag the offset and length of a memory block for the streamed sound file. FSOUND_Stream_Play starts streaming the file flagged with music_handle. I used channel index 1 because we'll use the same to control the volume of the streamed music track (a way to divide the volume of sound effects and music). Note how I used MusicVolume to set the volume of the streamed track (255 max, 0 mute). FSOUND_SetVolumeAbsolute sets a channel volume linearly. This function is NOT affected by master volume. It is used when you want to quiet everything down using FSOUND_SetSFXMasterVolume, but make a channel prominent. To stop streaming a sound file I use a following subroutine: SUB stopStreamMusic() IF PlaySound = TRUE THEN FSOUND_Stream_Stop music_handle FSOUND_Stream_Close music_handle END IF END SUB I recommend you to stop streaming a file before you change it to another one. If you are more imaginative, you can come up with volume fade in / fade out effects when tracks are changed, but I don't want to complicate this tutorial with that. For playing sound effects I use the following subroutine in conjunction with a volume setting subroutine: SUB playsample (plsnd as integer ptr) IF PlaySound = TRUE THEN FSOUND_PlaySound (FSOUND_FREE, plsnd) setSoundVolume END IF END SUB SUB setSoundVolume DIM SetVol AS INTEGER IF PlaySound = TRUE THEN
IF SFXVolume = 0 THEN SetVol = 0 IF SFXVolume = 1 THEN SetVol = 63 IF SFXVolume = 2 THEN SetVol = 126 IF SFXVolume = 3 THEN SetVol = 190 IF SFXVolume = 4 THEN SetVol = 255 FSOUND_SetSFXMasterVolume(SetVol) IF MusicVolume = 0 THEN SetVol = 0 IF MusicVolume = 1 THEN SetVol = 63 IF MusicVolume = 2 THEN SetVol = 126 IF MusicVolume = 3 THEN SetVol = 190 IF MusicVolume = 4 THEN SetVol = 255 FSOUND_SetVolumeAbsolute(1, SetVol) END IF END SUB Note how the sound effects volume is set every time a sound effect if played, and how in the same time the music volume (channel 1 volume) needs to be RESET. To play sound effect 1 use: playsample (sample(1)) You don't have to use a sample array like it did. If you for example create an integer pointer named splash and properly load a sound effect with it, then you'll use: playsample (splash) To test all this code create a loop like this one: SCREENRES 640, 480, 32, 1, GFX_WINDOWED DO IF PlaySound = TRUE THEN FSOUND_Update LOCATE 1,1 PRINT "PUSH ESC TO END PROGRAM" PRINT "PUSH 1 AND 2 TO TEST SOUND EFFECTS" PRINT "PUSH F1 AND F2 TO CHANGE THE WATER SOUND VOLUME" IF MULTIKEY(SC_1) THEN playsample (sample(1))
SLEEP 1000 END IF IF MULTIKEY(SC_2) THEN playsample (sample(2)) SLEEP 1000 END IF IF MULTIKEY(SC_F1) THEN MusicVolume = MusicVolume - 1 IF MusicVolume < 0 THEN MusicVolume = 0 setSoundVolume SLEEP 1000 END IF IF MULTIKEY(SC_F2) THEN MusicVolume = MusicVolume + 1 IF MusicVolume > 4 THEN MusicVolume = 4 setSoundVolume SLEEP 1000 END IF SLEEP 10 LOOP UNTIL MULTIKEY(SC_ESCAPE) FSOUND_Close Use 1 and 2 to test the two sound effects, F1 and F2 to change the music volume. I've been told that using FSound_Update is not necessary, but heck, it doesn't hurt. Note how FSound_Close is used before the program ends. Always be sure to close FMOD when you end your program. The entire code so far: codever1.txt Few more statements I want to show you. To pause currently streamed music track use FSOUND_SetPaused (1, 1) Note that the first parameter is the channel, so this will work only if you are streaming the music track in that channel. To start streaming it again use: FSOUND_SetPaused (1, 0)
That's all!
This is just the surface of FMOD. I warmly recommend you to explore "fmod.bi" and FMOD documentation. Happy coding!