OpenAL Sound System - is slow!

I know what you are think i find slow spots and in turn it turns out to be me. I hope this will turn out the same way. Currently it can take up 50% of my python “App” time - that is not good most of the other tasks did take up more time but i have significantly cleaned them up. So lets cut to the point first is a python task that does:

Audio3DManager.update which calls “getSoundVelocity” for each of its known sounds. If that call is removed this task takes no time

    def getSoundVelocity(self, sound):
        """
        Get the velocity of the sound.
        """
        if (self.vel_dict.has_key(sound)):
            vel = self.vel_dict[sound]
            if (vel!=None):
                return vel
            else:
                for known_object in self.sound_dict.keys():
                    if self.sound_dict[known_object].count(sound):
                        return known_object.getPosDelta(self.root)/globalClock.getDt()
        return VBase3(0, 0, 0)

I don’t really know which one is causing the problem. I see keys() used a lot in the code base aren’t iterkeys() faster? In py3k iterkeys() will become keys(). Ok now onto the next taks which is much slower.

That one is in showbase:

    def __audioLoop(self, state):
        if (self.musicManager != None):
            self.musicManager.update()
        for x in self.sfxManagerList:
            x.update()
        return Task.cont

As it happens both musicManager and the sfxManagerList contains one OpenALAudioManager - at first i thought it was the same one but it turnes out it has 2 different OpenALAudioManagers to update on. Without quests this update takes a long time maybe even with duplicating the effort


////////////////////////////////////////////////////////////////////
//     Function: OpenALAudioManager::update
//       Access: Public
//  Description: Perform all per-frame update functions.
////////////////////////////////////////////////////////////////////
void OpenALAudioManager::
update() {

  // See if any of our playing sounds have ended
  // we must first collect a seperate list of finished sounds and then
  // iterated over those again calling their finished method. We 
  // can't call finished() within a loop iterating over _sounds_playing
  // since finished() modifies _sounds_playing
  SoundsPlaying sounds_finished;

  double rtc = TrueClock::get_global_ptr()->get_short_time();
  SoundsPlaying::iterator i=_sounds_playing.begin();
  for (; i!=_sounds_playing.end(); ++i) {
    OpenALAudioSound *sound = (*i);
    sound->pull_used_buffers();
    sound->push_fresh_buffers();
    sound->restart_stalled_audio();
    sound->cache_time(rtc);
    if (sound->status()!=AudioSound::PLAYING) {
      sounds_finished.insert(*i);
    }
  }
  
  i=sounds_finished.begin();
  for (; i!=sounds_finished.end(); ++i) {
    (**i).finished();
  }
}

I don’t see any thing particularly speed uttering here maybe you do?

Another funny thing i noticed is that i can stop __audioLoop form running at all (saving lots of CPU cycles) and the sound still plays! Yes really it does play but only for a second or so then it does out unless i force another sound to play (with click or some thing) … maybe i can just force the sound to play every once in a while to keep the sound system moving and save me about 50% of the app time - i think i will find other drawbacks to this method though.

I’ve never really tried to performance-benchmark the OpenAL code.

First, remember that the free version of OpenAL is not hardware accelerated. All that sound-decoding is being done in software. I wouldn’t play more than 4 or 5 sounds at a time.

Second - it supports streaming sounds from disk. If the sound file is larger than a certain threshold, it will play it straight from disk rather than load it into RAM. I believe there is a way to tweak the threshold there. But streaming multiple files from disk concurrently could be an issue.

Third, that python code to update sound positions is… well, it’s in python. How many sounds do you have in the 3D manager at a time?