JavaZoom resources on github

I just found out (two years after the fact) that a bunch of JavaZoom audio resources have source posted on GitHub.
These include mp3 and ogg/vorbis libraries.

More here.

Besides the fact that more formats are supported, is there any valid reason for using these sound libraries instead of the JavaFX mediaplayer? The thing is, I have spikes/hickups in my gameloop for Bee vs Mites when starting/stopping mp3’s. They don’t always occur, but when they do, it’s definitely the mediaplayer. I tried using WAV’s, which kinda improved the situation (due to absence of decompression I guess, drawback is ofcourse the size of the WAV’s (roughly 5 to 7 times bigger)) but they only run once and don’t loop (bug?). I wanted to stream the mp3’s directly from memory, but the mediaplayer only works with files and not with inputstreams. Are these spikes normal behaviour for mediaplayer/mp3? And ofcourse the big question: do the sound libraries have the same problem? Or do they play everything seamlessly?

Yes, there is a valid reason to use these instead of JavaFX mediaplayer!

By spikes, I’m thinking you mean the same thing as clicks? In other words, it doesn’t just start or stop, but there is also a loud click that occurs. This would indicate discontinuities in the sound wave. (If the discontinuities are with the beginning or end of the sound file, probably should use Audacity to edit and put a short fade-in at the beginning or fade-out at the end as needed. Garbage in garbage out also pertains to sound cues.) These clicks can also occur with volume changes (sometimes it is called a “zippering” artifact).

Hickups would indicate dropouts, meaning that the processor is unable to keep up with providing data to the DAC in time. Decompressing does add to the cpu cost for processing a sound and make it more likely that a gap larger than the buffer size would occur.

I may be wrong, but I think the volume controller for the JavaFX media player is kind of lame, and only presents volume changes to the audio stream at each internal buffer transition.

However, with these libraries, you can do the following:

  1. decompress the sound and hold it in memory yourself
  2. output the data via a SourceDataLine
  3. write your own volume changers that spread the volume change out over enough frames that discontinuities are avoided.

This is a fair bit of work, so I recommend using the AudioCue library to help with the above. It functions like a Clip, but volume can be changed in real time and does so smoothly because it is implemented on a per-frame basis. (It is only a half-dozen files, a couple being just interfaces, and the code is right there available to examine/edit as needed. And it is free.)

In this case, you would decompress the sound with the help of one of these libraries into an array of PCM floats (range -1 to 1). This might take a bit of rewriting, but the hard stuff is already done. Then use the array as a data source for the AudioCue. Since the decompression is done in advance, when playing a sound, the cpu runs significantly faster than the DAC, and you can even set the audio thread priority to HIGH and it will spend most of its time blocking on the SDL write method and not hurt performance of the graphics.

For example, I rewrote a part of a routine that decompresses ogg files and short-cut the process at the stage where it had converted to signed normalized floats, but before it changed those floats to audio bytes and wrote to the java audio output. That is a big part of how the forest ambience app managed to present as much audio as it did yet stay under 2MB.

No, I have no clicks. What I meant by spikes/hickups is a slight halt of execution (just a few dozen millisecs, yet noticeable). I solved the problem. The WAV’s were longer than needed, for I used different speeds for the gameloop on different difficulty levels, so I had to fade out and stop the WAV’s when a certain situation (a scrolling effect) ended, depending on the speed of the gameloop. Now the gameloop runs at the same speed on any difficulty level (only the enemies run faster at higher diff levels), so the WAV’s are the same fixed length as the scrolling effect. Fade is now in the WAV and it cycles once so there’s no need for stopping through code. And it was the stopping of the WAV that caused the slight delay in execution. So… solved :slight_smile:

About volume changes: I do not have any problems with that. When I start a minigame from the main game screen, the transition is smooth. One MP3 fades out over a timespan of 2500 ms, while at the same time another MP3 fades in over the same period of time. Sounds cool and works like a charm (ofcourse, this is not an audioclip (fire&forget, changes in volume no longer possible), but a mediaplayer).

I am seriously considering using your AudioCue library for my next game (Bella’s Journey, weird adventure game with psychedelic touch, currently pre-alpha, further development relies heavy on sales of Bee Aware, so chances are I’ll never finish it ;D). I especially like the idea of soundscapes (already had a taste of that with your ‘noise sculpting experiments’, played with the wind a few months ago).

Glad to hear you identified the problem and it now works.

Fades over longer periods will be less prone to zippering than quick fades.

If you have that, you have a problem in your code, calling something that’s not real-time safe (blocking) in a thread that needs to be.

@nsigma It only occurred on a specific point, and as you might have read above, that problem is solved 8)

For now, on the setups you’ve tested! :wink: If you can’t guarantee the real-time / asynchronous characteristics of a third-party library, it’s always good to consider handing (audio) event scheduling on to a secondary thread.

@nsigma I hear you :slight_smile: I’ll certainly consider this for my next game!