!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> » Taming SoundEngine Processor Utilization -- Mobile Perspectives

Taming SoundEngine Processor Utilization



By paul ~ July 22nd, 2009. Filed under: Resources.

If you’re using the SoundEngine example code from Apple for OpenAL sounds on iPhone, I have a tip for you.  I ran into a serious processor utilization problem when using SoundEngine_LoadLoopingEffect() to load a sound effect that had a long preamble and then transitioned into a steady-state loop.  At first glance, this function looks ideal for such a thing because it will allow you to load a sound to be played when the effect starts, then a sound that is looped, then a sound that is played when the effect is stopped.  What I found was that, while the preamble (called the AttackBuffer in SoundEngine) is playing, SoundEngineEffect::PlaybackProc() hogs the processor.  This led to serious frame rate issues in iPunt .

The cause is the following code in SoundEngineEffect::PlaybackProc()

  if (THIS->HasAttackBuffer())
  {
    ALint numBuffersProcessed = 0;
    while (numBuffersProcessed < 1)
    {
       alGetSourcei(THIS->GetEffectID(), AL_BUFFERS_PROCESSED, &numBuffersProcessed);
         AssertNoOALError("Error getting processed buffer number", end)
    }

While the attack buffer is playing, you’re in a tight polling loop waiting for it to complete.  This is no problem if the preamble is really short, but for OpenGL games, it’s going to cause problems for any sound longer than a fraction of a frame.

The fix, fortunately, is simple.  Sleep this thread for a few milliseconds each iteration of the polling loop in order to give the rest of your application a chance to run.

The modified code is:

  if (THIS->HasAttackBuffer())
  {
    ALint numBuffersProcessed = 0;
    while (numBuffersProcessed < 1)
    {
       alGetSourcei(THIS->GetEffectID(), AL_BUFFERS_PROCESSED, &numBuffersProcessed);
         AssertNoOALError("Error getting processed buffer number", end)
       usleep(5000);  // Sleep for 5 mS each polling loop
    }

This little change makes all the difference for this bit of code and makes it suitable for long (> 1second) preambles.

I’ve found SoundEngine to work pretty well, although I have had to make a number of modifications to it for my specific application.  However, I think I’m at the point where I need to write my own OpenAL sound processing class library.  I’d be interested to hear from some of you to see what you’re using for game sound.

Comments are closed.