Streaming two OGG files at the same time causes crackling

Hello guys.

I’m making a sound engine for my game, and so far, it’s been pretty easy and straight forward. Everything is working pretty well.

I use and load WAV files into memory and dispose of them later for sound effects, and for music I stream in OGG files with the OggInputStream class I found on this very site. I also use jorbis for loading in the sound.

Now, everything works, but when I stream two OGG’s at the same time, the sound crackles really bad. After doing some research on the internet, I found that people who use OpenAL in Objective-C had the same problem, and apparently solved it by changing how the buffers allocate memory. Of course, I’m completely unsure if such a fix is possible in Java. Neither do I know anything about Objective-C. I’m also fairly new to OpenAL, so a lot of this is pretty Alien to me.

Does anyone know anything about this? If you need more elaboration, please do just ask.

I don’t know a lot about the technologies you are using–I’ve used ogg & jorbis, and decided they were not for me. But they work for most people. However, I know a couple things about sound programming in general and maybe the following will help.

When you say crackle, does it seem to be related to a lot of starting and stopping, or are harsh sounds that are not on the originals playing?

If the first case, the code that is playing back probably is having trouble keeping current. Enlarging the buffers would help, but would also add to the latency. Usually with sound tracks (as opposed to cues for game play) latency is not such a big deal.

In the second case, the volumes from the two tracks could be overpowering the playback code. In this case, you would have to come up with a way to play back the cues at a lower volume. One possibility is to rerecord the cues at lower volumes before saving them as oggs. Another is to programmatically lower the playback volume and see if that helps.

Why two at once? This is unusual, yes? Ogg is computationally expensive, and you are doubling the cpu cost. Is this a situation where the two files can be remixed together outside the program into a new, single cue? Audacity is great for that sort of thing, and free. (Just make sure you don’t download a fake version.)

Well, my idea was to have ambience playing along with the music. However, I can see the possibility of fusing the ambience and the fighting theme files and then making a mixer of some kind to just turn up the fighting channel when I’m in combat. However, I wouldn’t even know where to start on such a feature in OpenAL.

The crackles happen in a pattern, as in there’s like a rhythm to how often it happens. I think it may be the first case. Right now, the ByteBuffer that streams them is allocated to be 4096 * 8, but do you think I should increase it? If so, how much?

Right now the streams are updated in their own thread separate from the game, and I have it sleep for 1000/30 milliseconds to try and keep the engine from stressing the computer too much.

I could also try lowering the volume. Isn’t there a command in OpenAL for this? I think it was changing the Sources gain, correct?

Thank you very much for your input.

The LWJGL wiki has some examples on OpenAL, which include handling volume for a source. OpenAL isn’t very beginner-friendly, so if you aren’t understanding it, you are kind of “on your own.”

Have you tried other libraries like Paul’s Sound System? It should support multiple OGG streaming. Then at least you will know whether the problem lies with your own codebase, or something else.

There is also TinySound, which will do the mixing in software using JavaSound and in theory should get rid of OpenAL issues.

I understand a lot of it.

I personally didn’t like Pauls system. It takes too much initialization and was extremely buggy when I used it. A lot of the locational based sound didn’t work at all. Tiny Sound doesn’t provide 3d sound, but is very well written.

I programmed my own to be a lot simpler yet provide the same amount of functionality. You can start it up and play a sound with 3 lines of code. It’s been pretty successful up until this point. Like I said, streaming works perfect. Just two at a time stirs trouble. I can load and use as many WAVs as I want though, seeing as I load them completely in. (WAVs are being used for sound effects, so each one is about 10-50 KBs).

I thought I had left this message last week: the issue could very well be that jorbis is not concurrency safe. I recall looking at the code before and wondering about some of the practices such as public variables being changed. Mostly I couldn’t follow the details so maybe it is fine. But I wouldn’t be surprised if there are concurrency issues. One test might be to make two entirely separate instances of jorbis and see if the problem still occurs? I don’t know if there are statics that would prevent this or require some renaming to coax program into allowing two truly independent instances.