OpelAL memory player interference


We're seeing a problem when playing sounds using OpenAL. We're playing (from memory, not streaming) quite a few different sounds using different pitch/volume combinations, and occasionally, pitch+volume settings carry over from one sound to another. This means that a sound (usually an ambient sound) gets played at a totally incorrect volume and/or pitch which is jarring. I'm not sure if it's always the case that both sound and pitch carry over from one sound to another, or if it's possible for just one of them to carry over. The problem happens frequently, at least every 5 minutes or so when playing our game (maybe more, since it's only easy to hear the more extreme differences). From a quick glance through the logs, it seems like we're peaking at playing maybe 8 or so sounds/second, and we have about 100 different sounds in memory.

I  expect there are a few ways this can happen (almost impossible to tell which is which from in-game):

  • the right sound is played, but it inherits sound/pitch from the previous sound
  • the right volume/pitch settings are used, but the underlying sound is not switched from the previously buffered sound
  • an in-use buffer is reused for a new sound, but only the volume/pitch settings are applied, not the new sound

    For some reason, I think the third alternative is the most likely, but that's only a gut feeling and quite possibly wrong - the problem could very well be in our code, not lwjgl or jme. I guess it's only natural to think (hope?) it's somebody else's fault at first. :slight_smile:

    Anyway, what I'm after with this post is just to see if something similar has happened to anybody else, and if anybody has a hint as to how best to troubleshoot this?



Even worse is the problem could be OpenAL or OpenAL on your specific system, so it'd help if you could tell us if this problem occurs on several machines of just your own…

Further than that, I'd recommend running your application in debugging mode, and pausing execution when you hear a wrong sound… that should help you debug if it's an actual problem with variables being set incorrectly, or if it's another problem.

LWJGL is just a thin wrapper, and pretty mature (though nothing is of course perfect). Our own sound system is relativly new so could have a couple of bugs, though afaik we don't have any complex systems with reusing Buffers and such.

Hmm, well that definitely sounds like a problem.  (sorry, bad pun)  Are you seeing any warnings or such in the log?

We do cache buffers, but only for loading purposes.  We also reuse OpenALSource objects, but all properties are reapplied every time the source is played.  Looking at the code I don't see a good way that any of your 3 ways could happen… (see the play() method of OpenALMemoryAudioPlayer)  My personal guess would be a threading issue, but as you can see in the code, even that is pretty well locked down.

You are definitely stressing it more than any of my tests.  Do you have a test case I could play with to try to reproduce and debug this problem?

Also, I'm assuming you are using jmex.audio.* and the latest version of it from cvs?

Thanks for the responses - I can confirm that the problem occurs on every machine we have tried it on (around 10 or so), and that we're using jmex.audio.*, but not the very latest from cvs, just the rc1 version. I'll give the cvs version a shot today, to see if it happens there as well.

As for pausing execution when there is an incorrect sound, we've been doing that, and as far as our own debug logs show, we're setting volumes and pitches correctly every time.  I've not done detailed debugging on the jME level other than adding tracing of which OpenAL source and buffer id:s are used to see if it could be some broken buffer or something, but I haven't found any pattern at all there.

I did a lot of digging around yesterday and tried to reproduce the problem with a much simpler application than the full game, but no luck. The main difference between the test application and the full game is probably the way that we're dealing with ambience sounds. Basically, we have a set of ambience states (in menu, game paused, goal scored, replay, etc.), and three ambience 'channels' for which different actions can be configured (play track, stop current track, change current track volume, do nothing). "Play track" means "stop current track, if any, and start the specified track with looping set to true", the others are pretty self-explanatory. My plan is to try to disable some of those features to see if that can give any clue to where the problem is.

A little brain dump in the middle of debugging this - I'm getting pretty tired of it having spent a couple of days on it. This is the current state:

  1. Upgrading jME to the latest CVS version doesn't help.
  2. The most easily identifiable scenario is this: we have ambient, looping sounds that should continue to play until the game shifts into the next ambience state. Typically these sounds are played at a volume of about 0.2-0.3. Sometimes, pretty rarely, one of these sounds changes volume upwards (not sure if it's always upwards or if that's just the case that we can hear), and stops looping. Checking AudioTrack.isPlaying() for the audio track that stops shows that the OpenAL system is aware of the fact that this particular track has stopped. It's therefore the case that for some reason, parameters for an existing, currently playing looping track are changed so that the volume increases and the looping stops - it's not the case that a sound that should normally be played in a loop gets played using the wrong parameters.
  3. We have, on rare occasions, heard effect sounds being affected in the same way. This is much harder to hear (and probably rarer) because effect sounds play for such a short while, so probably this could happen to any sound, but it's more likely to happen to looping sounds and that case is easier to identify.
  4. The problem seems to happen pretty quickly. In my last test, the first ambience loop stopped after playing 225 sound events - 60 different OpenAL source id:s were used and 59 different buffers. The sources were used between 2-4 times each (so the recycling of buffers in OpenALSystem.getNextFreeSource() seems to work), and the buffers were played between 1 and 12 times each. It took about 3 minutes until the problem showed itself. The loop that stopped is about 20 seconds long, so something happened in those last 20 seconds, but I don't know what.
  5. As far as I can tell, not yet having gone really in-depth with source id:s etc, it's not the case that a particular source id is reused to play another track. In the example above, the source ID used to play the ambient sound was never used by jME to play another sound before the looping sound stopped.

    I think I'll give this a little rest - maybe somebody can see some kind of pattern and give me some idea for how to continue looking at this. As llama says, the OpenAL wrapper in lwjgl is really thin, so my guess is that the problem is either some kind of buffer overflow in the native OpenAL code, or something in jME that I haven't been able to figure out yet - I can't rule out the possibility of a bug in our code yet, but I've spent days on this and I don't see how a problem on that level could have this effect.