Last Ray of Hope Home of Kaluriel Hargrove

30Sep/08Off

Athena: Playing Sound with FMOD Soundbanks

Similar to my previous entry for AGT assignment, Legend of Bob: Playing Sound with FMOD, this goes further into the world of FMOD. I needed more control over sound for my Athena engine, and looking more into the FMOD APIs, I discovered that FMOD Ex uses soundbanks, which you can change how the sound is by changing values to variables you setup when creating them.

As well as this, with soundbanks you can link multiple audio sources and get them compiled into a single file that will be loaded with the soundbank, specifying even the maximum number of concurrent streams that should be playable for individual audio. As before, most of this code can be found in the FMOD documentation.

There seems very little support for Mac users when it comes to FMOD, so when you find a version, hold onto it when upgrading, newer versions may just break.

Creating a FMOD Soundbank

fmod_soundbank_tut_03The first thing you'll need to be able to make a soundbank is download FMOD Designer (get a version that your library you use in code is compatible with).

Open up FMOD Designer, goto the File menu and select New Project, name this new project "testSoundbank".

fmod_soundbank_tut_04Select and expand the "untitled" folder in the Hierarchy window that is on the Events tab. We need to rename this to something we can remember, so lets rename it to "test" in the property window at the bottom.

If you have done right the change will be reflected in the Hierarchy window.

fmod_soundbank_tut_051Now we have a single event called "event00", we want to rename this too, but to "someTestSound" this time. Select it and scroll down the property window until you find the "name" parameter.

Again the change will be reflected in the Hierarchy window.

fmod_soundbank_tut_061Well that is the basic setup of our soundbank, however if we try to play that event now, we will hear nothing, so what we need to do is load in a wavetable.

Goto the Sound definitions tab, and right click on the empty space to the left side. Now select Add sound definition(s) from wavetables... and a file open dialog will appear.

fmod_soundbank_tut_08Select a file you want to import (I chose one called "bluh-no-twisting-knackers.mp3"), and click Open. You can play around with the parameters for this sound, but it won't be covered in this guide.

There are descriptions of what they do in the documentation.

fmod_soundbank_tut_09Go back to the Events tab and double click on "someTestSound" in the Hierarchy window, this will take us to this event within the Event editor tab.

Right click on the right hand side of "layer00" in the grey box (below where it says "Right-click here to add an event parameter") and select "Add sound...".

fmod_soundbank_tut_10Select the wavetable we just previous imported, and set "Loop mode" to "Oneshot". Finally click OK to add this sound to the event.

Now all that is left to do is build the FMOD soundbank. Goto the Build menu and select "Build project...".fmod_soundbank_tut_12

Make sure to check the box next to the wave bank associated with the wavetable you just imported. And click Build.

After a few moment and a progress bar, a message box saying "Build Complete. Took XX:YY:ZZ" will appear.

If you goto the folder where you created your FMOD project there should be a few new files there. You want the ".FSB" which is the soundbank, and ".FEV" which is event information. These two must be kept together when loading them into your application.

Well that is how to make an FMOD soundbank, on the next page I'll show you the code for setting up FMOD in code to load and eventually play a sound in a soundbank.

Tagged as: , , , No Comments
22Mar/08Off

Legend of Bob: Playing Sound with FMOD

FMOD LogoA few month ago I gave up on the idea on using OpenAL for playing sound effect since trying to get MP3s to play with it was getting annoying. A friend recommended whilst in the Student Union to use FMOD, so I switched over and found it did everything I needed, plus there was plenty of documentation and examples.

So here is some basic code for getting audio playing using FMOD, as well as a few additional functions. I've only allocated blocks for playing 10 sounds (if more than 10 sounds are attempted to be loaded, LoadSoundByFile() returns -1).

Here is the header for my sound manager.

#ifndef SOUNDMANAGER_H_INCLUDED
#define SOUNDMANAGER_H_INCLUDED
 
// --- [ libraries ] ------------------------------------------
#pragma comment(lib, "fmodex_vc.lib")
 
// --- [ includes ] -------------------------------------------
#include <fmod.hpp>
 
// --- [ definitions ] ----------------------------------------
#define SOUND_LOOP_INFINITE -1
#define MAX_NUM_SOUNDS 10
 
// --- [ class ] ----------------------------------------------
class SoundManager
{
// Attributes
private
	FMOD::System * m_pSystem;
	FMOD::Sound * m_pSound[MAX_NUM_SOUNDS];
 
// Functions
public:
	// Constructor
	SoundManager();
 
	// Destructor
	~SoundManager();
 
	// Load Sound from File
	int LoadSoundFromFile( const char * inFilename );
 
	// Free Sound
	void FreeSound( const int inSoundId );
 
	// Play Sound
	void PlaySound( const int inSoundId );
 
	// Set Position
	void SetSoundPosition( const int inSoundId, const int inPositionInMilliseconds );
 
	// Set Loop Count
	void SetSoundLoopCount( const int inSoundId, const int inCount );
 
	// Set Loop Points
	void SetSoundLoopPoints( const int inSoundId, const int inStartInMilliseconds, const int inEndInMilliseconds );
};
 
#endif

 

For background music, I've also included code so that the sound can be looped forever, and since not all sounds will be looping from the beginning, I've added a function to set where the loop repeats from and begins again. When a sound is not being used anymore, FreeSound() should be called for the id returned by LoadSoundFromFile().

// --- [ includes ] -------------------------------------------
#include "SoundManager.h"
 
// --- [ constructor / destructor ] ---------------------------
SoundManager::SoundManager()
{
	for( unsigned int i = 0; i < MAX_NUM_EFFECTS; ++i )
	{
	m_pSound[i] = 0;
	}
 
	// Create FMOD SoundSystem
	FMOD::System_Create( &m_pSystem );
 
	// Check FMOD Version
	unsigned int fmodVersion;
	m_pSystem->getVersion( &fmodVersion );
	assert( fmodVersion >= FMOD_VERSION )
 
	// Initialize FMOD SoundSystem
	m_pSystem->init(32, FMOD_INIT_NORMAL, 0);
}
 
SoundManager::~SoundManager()
{
	// Free FMOD Sounds
	for( unsigned int i = 0; i < MAX_NUM_SOUNDS; ++i )
	{
		if( m_pSound[i] )
		{
			m_pSound[i]->release();
		}
	}
 
	// Free FMOD SoundSystem
	if( m_pSystem )
	{
		m_pSystem->close();
		m_pSystem->release();
		m_pSystem = 0;
	}
}
 
// --- [ functions ] ------------------------------------------
int SoundManager::LoadSoundFromFile( const char * inFilename )
{
	for( int i = 0; i < MAX_NUM_SOUNDS; ++i )
	{
		if( !m_pSound[i] )
		{
			m_pSystem->createSound( inFilename, FMOD_SOFTWARE, 0, &m_pSound[i] );
			return i;
		}
	}
 
	return -1;
}
 
void SoundManager::FreeSound( const int inSoundId )
{
	assert( inSoundId >= 0 && inSoundId < MAX_NUM_SOUNDS );
 
	if( m_pSound[inSoundId] )
	{
		m_pSound[inSoundId]->release();
		m_pSound[inSoundId] = 0;
	}
}
 
void SoundManager::PlaySound( const int inSoundId )
{
	assert( inSoundId >= 0 && inSoundId < MAX_NUM_SOUNDS );
 
	if( m_pSound[inSoundId] )
	{
		FMOD::Channel * channel;
		m_pSystem->playSound( FMOD_CHANNEL_FREE, m_pSound[inSoundId], false, &channel );
	}
}
 
void SetSoundPosition( const int inSoundId, const int inPositionInMilliseconds )
{
	assert( inSoundId >= 0 && inSoundId < MAX_NUM_SOUNDS );
 
	if( m_pSound[inSoundId] )
	{
		m_pSound[inSoundId]->setPosition( inPositionInMilliseconds, FMOD_TIMEUNIT_MS );
	}
}
 
void SoundManager::SetSoundLoopCount( const int inSoundId, const int inCount )
{
	assert( inSoundId >= 0 && inSoundId < MAX_NUM_SOUNDS );
 
	if( m_pSound[inSoundId] )
	{
		m_pSound[inSoundId]->setLoopCount( inCount );
	}
}
 
void SoundManager::SetSoundLoopPoints( const int inSoundId, const int inStartInMilliseconds, const int inEndInMilliseconds )
{
	assert( inSoundId >= 0 && inSoundId < MAX_NUM_SOUNDS );
 
	if( m_pSound[inSoundId] )
	{
		m_pSound[inSoundId]->setLoopPoints( inStartInMilliseconds, FMOD_TIMEUNIT_MS, inEndInMilliseconds, FMOD_TIMEUNIT_MS );
	}
}

 

All timing in my code is in milliseconds, but it can be changed to another supported FMOD time unit.

Tagged as: , , , No Comments