Sep
30
2008

Athena: Playing Sound with FMOD Soundbanks

Setting up FMOD Ex in Code

The base object that will be used for playing sounds within a soundbank is an Event. So I have wrapped this FMOD class within my own class for abstracting the functions so that if need be, it can be swapped out for another system but maintain functionality.

The following code is my event class header, using advance declaration, I don’t need to include the FMOD header until the source file.

#ifndef SOUNDBANKEVENT_H_INCLUDED
#define SOUNDBANKEVENT_H_INCLUDED

//
//
namespace FMOD
{
class Event;
}

//
//
class SoundEvent
{
friend class Soundbank;

//
// Attributes
private:
FMOD::Event * m_pEvent;

//
// Functions
public:
//
//
SoundEvent();

//
//
void Play();

//
//
void Stop();

//
//
bool IsPlaying();

//
//
void SetParameter( const char * inName, const float inValue );

//
//
float GetParameter( const char * inName );

//
//
bool IsValid() const
{
return m_pEvent != 0;
}
};

#endif

Most functionality for a soundbank event is simply gotten, however since events can have multiple streams, the same FMOD Event object will be used for all. So getting information about whether a single event stream is playing is not as simple, we can only check if any stream is active.

Here is the source for the soundbank event class.

//
//
#include "SoundbankEvent.h"
#include <fmod_event.hpp>

//
//
SoundEvent::SoundEvent()
:
m_pEvent( 0 )
{
}

//
//
void SoundEvent::Play()
{
assert( m_pEvent );
m_pEvent->start();
}

//
//
void SoundEvent::Stop()
{
assert( m_pEvent );
m_pEvent->stop();
}

//
//
bool SoundEvent::IsPlaying()
{
assert( m_pEvent );

FMOD_EVENT_INFO eventInfo
m_pEvent->getInfo( NULL, NULL, &eventInfo )
return eventInfo.channelsplaying > 0;
}

//
//
void SoundEvent::SetParameter( const char * inName, const float inValue )
{
//
// Get Event Parameter
FMOD::EventParameter * parameter = 0;

m_pEvent->getParameter( inName, &parameter ) );
assert( parameter )

//
// Check new value is within range
float minimum, maximum;
parameter->getRange( &minimum, &maximum );
assert( inValue >= minimum && inValue <= maximum );

//
// Set Value
parameter->setValue( inValue );
}

//
//
float SoundEvent::GetParameter( const char * inName )
{
//
// Get Event Parameter
FMOD::EventParameter * parameter = 0;

m_pEvent->getParameter( inName, &parameter ) );
assert( parameter )

//
// Get Parameter Value
float value = 0.0f;
parameter->getValue( &value )

return value;
}

A layer above the FMOD Events is the FMOD Soundbank itself. It isn’t used for much, its main functionality is just to get events from it so we can play sounds.

Here is the header for my Soundbank class.

#ifndef SOUNDBANK_H_INCLUDED
#define SOUNDBANK_H_INCLUDED

//
//
namespace FMOD
{
class EventProject;
}

class SoundEvent;

//
//
class Soundbank
{
//
// Attributes
private:
FMOD::EventProject * m_pEventProject;

//
// Functions
public:
//
//
explicit Soundbank( FMOD::EventProject * inEventProject );

//
//
bool GetEventByName( const char * inName, SoundEvent & outEvent );

//
//
bool IsValid() const
{
return m_pEventProject != 0;
}
};

#endif

And the source code for the Soundbank class to go with it.

//
//
#include "Soundbank.h"
#include "SoundbankEvent.h"
#include <fmod_event.hpp>

//
//
Soundbank::Soundbank( FMOD::EventProject * inEventProject )
:
m_pEventProject( inEventProject )
{
}

//
//
bool Soundbank::GetEventByName( const char * inName, SoundEvent & outEvent )
{
m_pEventProject->getEvent( inName, FMOD_EVENT_DEFAULT, &outEvent.m_pEvent );
}

Finally my Audio Manager class, expanded from the original audio manager used in my AGT work, this now using a namespace with Init() and DeInit() functions, and an Update() function that needs to be called every update cycle.

This manager is used to load the soundbank, here is the header.

#ifndef AUDIOMANAGER_H_INCLUDED
#define AUDIOMANAGER_H_INCLUDED

//
//
class Soundbank;

//
//
namespace AudioManager
{
//
//
void Init();

//
//
void DeInit();

//
//
void Update();

//
//
Soundbank * LoadSoundbankFromFile( const char * inFilename );
}

#endif

And finally here is the source code for Audio Manager, as you can see the initialisation code is almost exactly the same as the previous audio manager. However this time, we are using FMOD::EventSystem_Create() which is setup almost in the same way (only a slight different in the version check and init calls).

//
//
#include "AudioManager.h"
#include "Soundbank.h"
#include <fmod_event.hpp>

//
//
namespace AudioManager
{
FMOD::EventSystem * l_eventSystem;
bool l_isInitialised = false;
}

//
//
void AudioManager::Init()
{
assert( !l_isInitialised );
l_isInitialised = true;

//
// Create FMOD SoundSystem
FMOD_RESULT result;
result = FMOD::EventSystem_Create( &l_eventSystem );
assert( result == FMOD_OK );

//
// Get Base System Object for Version Test
FMOD::System * system;
unsigned int version;

result = l_eventSystem->getSystemObject( &system );
assert( result == FMOD_OK );

system->getVersion( &version );
assert( version >= FMOD_VERSION );

//
// Initialize FMOD SoundSystem
l_eventSystem->init( 32, FMOD_INIT_NORMAL, 0, FMOD_EVENT_INIT_NORMAL );
}

//
//
void AudioManager::DeInit()
{
assert( l_isInitialised );
l_isInitialised = false;

if( l_eventSystem )
{
l_eventSystem->release();
}
}

//
//
void AudioManager::Update()
{
l_eventSystem->update();
}

//
//
Soundbank * AudioManager::LoadSoundbankFromFile( const char * inFilename )
{
FMOD::EventProject * pEventProject;
FMOD_RESULT result;

//
// Load SoundBank
result = l_eventSystem->load( inFilename, 0, &pEventProject );
assert( result == FMOD_OK );

//
// Create Object for Event Project to return
return new Soundbank( pEventProject );
}

And finally on the last page I’ll show you have to use the soundbank.

[Previous Page...] [Next Page...]

Written by Kaluriel in: Athena,Code,Tutorials | Tags: , , ,

Pages: 1 2 3


No Comments »

RSS feed for comments on this post. TrackBack URL

Leave a comment

You must be logged in to post a comment.

Theme: TheBuckmaker.com Blog Themes | The best Webhosting Plans, Eigenes Internet Radio