Sunday, April 5, 2009

Sound state (playing, looping) support in SoundEngine.cpp

I have recently compared AVAudioPlayer with SoundEngine with the verdict that short of using AudioQueue, SoundEngine.cpp was better, at least for now.

The problem I faced with it is that it doesn't support query of the sound's states. This is not crucial, but because a game I was working on as a lot of objects falling at the same time, I wanted sounds to play simultaneously. I found it difficult to do if I couldn't find out if a sound is playing to start with.

I saw the same question poping up on some forums, with the usual answer being "use AVAudioPlayer", which is kind of a daft answer. So here is the simple changes I made to the original SoundEngine.h and SoundEngine.cpp to add support for the states.

Add this to the end of SoundEngine.h :

bool  SoundEngine_EffectIsPlaying(UInt32 inEffectID);
bool SoundEngine_EffectIsLooping(UInt32 inEffectID);

This in SoundEngine.cpp, in the SoundEngineEffect class :

ALenum GetState()
{
ALenum state;
alGetSourcei(mSourceID, AL_SOURCE_STATE, &state);
return state;
}
Add this in the same file, but in the OpenALObject class

bool EffectIsPlaying(UInt32 inEffectID)
{
SoundEngineEffect *theEffect = mEffectsMap->Get(inEffectID);
return (theEffect) ? (theEffect->GetState() == AL_PLAYING) : kSoundEngineErrInvalidID;
}
bool EffectIsLooping(UInt32 inEffectID)
{
SoundEngineEffect *theEffect = mEffectsMap->Get(inEffectID);
return (theEffect) ? (theEffect->GetState() == AL_LOOPING) : kSoundEngineErrInvalidID;
}
This is pretty self explanatory. GetState returns other values, like AL_PAUSED or AL_STOPPED, so the same method could be used for the whole range of states.

And finally, in the same file (SoundEngine.cpp), near the end where the Extern stuff is declared :

extern "C"
OSStatus SoundEngine_SetMaxDistance(Float32 inValue)
{
return (sOpenALObject) ? sOpenALObject->SetMaxDistance(inValue) : kSoundEngineErrUnitialized;
}

extern "C"
OSStatus SoundEngine_SetReferenceDistance(Float32 inValue)
{
return (sOpenALObject) ? sOpenALObject->SetReferenceDistance(inValue) : kSoundEngineErrUnitialized;
}

You can then use SoundEngine_EffectIsPlaying() and SoundEngine_EffectIsLooping() to query the sound's states.

2 Comments:

Blogger Deans said...

Hi-

Great tip! I really need this functionality in SoundEngine. Unfortunatly, my Objective-C code won't link with the changes indicated to the Sound Engine files. Everything compiles fine, but I get:

Undefined symbols:
"_SoundEngine_EffectIsPlaying", referenced from:
-[sndTstViewController loadView] in sndTstViewController.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

When I try to link

May 6, 2009 at 10:33 PM  
Blogger Deans said...

I wonder if the problem is with the last block of instructions. After looking more closely at the SoundEngine code itself, it seems like the code to add in the last block should be something more like:
---------------------
extern "C"
bool SoundEngine_EffectIsPlaying(UInt32 inEffectID)
{
return (sOpenALObject) ? sOpenALObject->EffectIsPlaying(inEffectID) : kSoundEngineErrUnitialized;
}

extern "C"
bool SoundEngine_EffectIsLooping(UInt32 inEffectID)
{
return (sOpenALObject) ? sOpenALObject->EffectIsLooping(inEffectID) : kSoundEngineErrUnitialized;
}

May 6, 2009 at 11:28 PM  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home