This is driving me insane. I have asked on Reddit and StackOverflow, and besides the fact that everyone is quick to jump down my throat about supposedly not "searching beforehand" (which I have, by the way... extensively), nobody has given me an answer.

The problem being, that I cannot seem to make the Clip class in Java's sampled sound package work the way I need it to. So I either need someone to look at the code for my Sounds class and tell me what fatal problem is causing my game to freeze up when I try to play the same sound multiple times simultaneously, or refer me to another library/package I can use.

So anyway, I'm trying to make use of the Clip class. (http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/Clip.html)I'm pre-loading the various sounds into an enumerator class and calling them statically as needed (ie: Sounds.WHATEVER.play()), but once I added sounds that would be played several times at once, simultaneously, the game started freezing up. I can only assume that the Clip class is not capable of doing this, but just in case I'm just doing something wrong... can someone look at my Sounds class and tell me if that is the case, or if I'm just doing something wrong?

Generic Zombie Shooter is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Generic Zombie Shooter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Generic Zombie Shooter. If not, see <http://www.gnu.org/licenses/>. **/packagegenericzombieshooter.misc;

If I need to use a different package or library, I will, but I really want to stick to core Java, at least for this project.

So, is there some fatal error with the way I'm handling this? Or is the Clip class just not capable of playing sound this way?I can provide information on how I'm playing the sound if need be, but really, all I'm doing is statically calling the play method for the required sound when that sound is supposed to be played (ie: firing a weapon, zombies moaning, etc). I think the reason this freezing never occurred before is because I was never playing the same sound multiple times simultaneously.

So... can someone spare me the insanity and tell me what it is exactly that I'm doing wrong?

Maybe try to use another Mixer. If you want to use a sound library, you can try Paul Lamb's Sound System or TinySound. Personally, I use Paul Lamb's Sound System with its plugin based on JOAL and my game works very well both with OpenJDK and Oracle Java

Maybe try to use another Mixer. If you want to use a sound library, you can try Paul Lamb's Sound System or TinySound. Personally, I use Paul Lamb's Sound System with its plugin based on JOAL and my game works very well both with OpenJDK and Oracle Java

I gave TinySound a look and all I could find was a Github page. I downloaded the ZIP of the project, but I can't figure out how to include it in my project in NetBeans and use the library. What do I do with the ZIP? I've tried including it as a library, adding it to the project, etc... but I can't import anything from the kuusisto package, nor can NetBeans find the TinySound class.

Except that if I close the sound, I have to reload the data, which isn't good for sounds that are played a lot. Also, when I said playing two sounds at the same time, I meant the SAME sound, not two different ones. So two calls to the same sound overlapping each other. THAT is why I use threads. Or at least, that's what some page on Google suggested.

Except that if I close the sound, I have to reload the data, which isn't good for sounds that are played a lot. Also, when I said playing two sounds at the same time, I meant the SAME sound, not two different ones. So two calls to the same sound overlapping each other. THAT is why I use threads. Or at least, that's what some page on Google suggested.

Clip can't seem to do that, which is why it's not going to work out.

I don't think playing a clip in a new thread allows you to play them simultaneously, to play two audio files simultaneously, you'll need two clips.

That said, it isn't very difficult to do. You'll want to cache all open clips with SoftReferences (or WeakReferences, but SoftReferences are more appropriate for caching.) When they're playing keep a hard references to them, and when they aren't keep a softreferences (via some caching module) This allows you to very quickly reset an unused to clip if you want to play it again and it's not currently being played (but it doesn't solve the problem of playing two clips simultaneously yet.) If the JRE decides it needs more memory and destroys your clip instance, you'll need to make sure you close it before giving it away to the JRE.

You'll also want to softreferences their raw data (for clips you want to play simultaneously) that you use to initialize the clip. By doing this, you minimize filesystem IO by caching a copy of the file in memory (with a byte buffer etc) which will allow you to very quickly initialize a new clip instance.

If you use this method, it is then important that you use an uncompressed audio format (like WAV) to minimize the pre-processing overhead induced by the compression. Which is fine since compressing small audio files (like the moan of a zombie, or gun fire) is almost pointless to do individually.

DON'T do this for large audio files like background music since it will probably kick everything out of the cache eventually. If you want to do this for compressed audio formats you need cache their decompressed raw data, otherwise initializing the clip will be expensive (due to the redundant process of decompressing the cached data.)

There are other more clever ways of doing it, but you'd have to ask someone more experienced with the Java Sound API.

Except that if I close the sound, I have to reload the data, which isn't good for sounds that are played a lot. Also, when I said playing two sounds at the same time, I meant the SAME sound, not two different ones.

Of course you can also play the same sound twice at the same time.

1 2

play("shoot.wav");play("shoot.wav");

You can also add a delay to get an echo effect.

1 2 3

play("shoot.wav");Thread.sleep(500);play("shoot.wav");

That the data has to be loaded twice should not be a problem since the OS has a file cache. But if you think it's an issue you could load the wav files into byte arrays and then create clips from those.

Except that if I close the sound, I have to reload the data, which isn't good for sounds that are played a lot. Also, when I said playing two sounds at the same time, I meant the SAME sound, not two different ones. So two calls to the same sound overlapping each other. THAT is why I use threads. Or at least, that's what some page on Google suggested.

Clip can't seem to do that, which is why it's not going to work out.

I don't think playing a clip in a new thread allows you to play them simultaneously, to play two audio files simultaneously, you'll need two clips.

That said, it isn't very difficult to do. You'll want to cache all open clips with SoftReferences (or WeakReferences, but SoftReferences are more appropriate for caching.) When they're playing keep a hard references to them, and when they aren't keep a softreferences (via some caching module) This allows you to very quickly reset an unused to clip if you want to play it again and it's not currently being played (but it doesn't solve the problem of playing two clips simultaneously yet.) If the JRE decides it needs more memory and destroys your clip instance, you'll need to make sure you close it before giving it away to the JRE.

You'll also want to softreferences their raw data (for clips you want to play simultaneously) that you use to initialize the clip. By doing this, you minimize filesystem IO by caching a copy of the file in memory (with a byte buffer etc) which will allow you to very quickly initialize a new clip instance.

If you use this method, it is then important that you use an uncompressed audio format (like WAV) to minimize the pre-processing overhead induced by the compression. Which is fine since compressing small audio files (like the moan of a zombie, or gun fire) is almost pointless to do individually.

DON'T do this for large audio files like background music since it will probably kick everything out of the cache eventually. If you want to do this for compressed audio formats you need cache their decompressed raw data, otherwise initializing the clip will be expensive (due to the redundant process of decompressing the cached data.)

There are other more clever ways of doing it, but you'd have to ask someone more experienced with the Java Sound API.

I don't want to seem stupid, but I didn't understand a lot of what you just said. Like I said, I don't have to stick to the Clip class... I was just hoping I could stay within the core Java packages.

I checked out TinySound, but I don't know how to include it in my project. I'm using NetBeans. I downloaded a ZIP of the TinySound repository on Github, but I'm not sure what to do with it. There aren't any JARs inside, so I can't use it as a library. How do I incorporate the .java files as a library?

Also, I removed the threads for playing the sound.

But yeah, loading the sound files on the fly isn't going to work. It would cause too much latency. Like Jeremy said, for a machine gun (and my game happens to have an Assault Rifle), it just won't work. My sounds are used too often.

You should stick to the Java Sound Library if you can, otherwise you don't get the advantage of plugging in other SPIs for different audio formats etc. Also, if you can it is always best to avoid any native dependencies.

You should stick to the Java Sound Library if you can, otherwise you don't get the advantage of plugging in other SPIs for different audio formats etc. Also, if you can it is always best to avoid any native dependencies.

I only use WAV files, so I don't see why I would need to worry about other audio formats. Also, I took a look at that Audio class you posted. Does it support the multiple plays of the same Clip simultaneously? Is it streamed? Like I said, streaming is absolutely not an option.

You should stick to the Java Sound Library if you can, otherwise you don't get the advantage of plugging in other SPIs for different audio formats etc. Also, if you can it is always best to avoid any native dependencies.

I only use WAV files, so I don't see why I would need to worry about other audio formats. Also, I took a look at that Audio class you posted. Does it support the multiple plays of the same Clip simultaneously? Is it streamed? Like I said, streaming is absolutely not an option.

Yeah, it will let you play the same audio file twice, and it adapts the ByteBuffer object to an InputStream for the JavaSound API, but it reuses the ByteBuffer - it doesn't load the same resource more than once and it caches the raw data to initialize a new clip if once is needed. It also caches the clip objects for re-use.

Also, I noticed a couple of weird imports at the top... specifically, the "jeva" package. Was that a typo, or is that an external library? Can I just include this file and use it as is, or do I need a library to use with it?

Also, I noticed a couple of weird imports at the top... specifically, the "jeva" package. Was that a typo, or is that an external library? Can I just include this file and use it as is, or do I need a library to use with it?

Those are external libraries, just delete them. You'll get a problem with AudioException not being found, and Core.getService(IResourceLibrary.class).openResourceRaw() or something like that. It's pretty easy to guess what they're supposed to do. Just write your own AudioException and openResourceRaw(string resource) is supposed to read the resource into a bytebuffer.

You should be able to just copy and paste it, noting the package will probably need to be changed.

But yeah, loading the sound files on the fly isn't going to work. It would cause too much latency. Like Jeremy said, for a machine gun (and my game happens to have an Assault Rifle), it just won't work. My sounds are used too often.

You could use your Sounds enum but put AudioData objects in there instead of clips.Or use SHC's classes, they look good too. Although I'm not sure if you can make a machine gun with them.SHC, maybe you could post a machine gun example using your library?

I checked out TinySound, but I don't know how to include it in my project. I'm using NetBeans. I downloaded a ZIP of the TinySound repository on Github, but I'm not sure what to do with it. There aren't any JARs inside, so I can't use it as a library. How do I incorporate the .java files as a library?

You need to build TinySound into a JAR yourself. Try creating a second project in NetBeans for TinySound, and copying all of the src folder contents from the zip file into it. You'll probably have to link the JARs in the lib folder into that project to get it to build. Either compile a JAR from the new TinySound project and include it in your existing project, or you should be able to link the TinySound project as a library directly.

I'd seriously get your head around the Java build process and creating / using JARs before you try playing with sound further.

And really, really, reallyDO NOT use Clip . It's implementation is not set up for doing what you want to do, or can end up working on one OS and not another.

But yeah, loading the sound files on the fly isn't going to work. It would cause too much latency. Like Jeremy said, for a machine gun (and my game happens to have an Assault Rifle), it just won't work. My sounds are used too often.

However of course it would be better to use Clip.loop for a machine gun but then the audio file may need some editing to make it sound correctly.

Ok, I've implemented this, but now I have one other question about how to use it... for sounds that I want to loop, but to stop when certain things happen (ie: flamethrower sound loop until player stops firing the weapon), how would I do that?

EDIT: I suppose answering the previous question might give me an idea on how to solve this one, but this is also a huge problem... there is no delay between the fire() calls to the Flamethrower weapon (whose sound is the only one in the game that loops), so they all play together REALLY rapidly, and it comes out as a raucous jumble of noise.

The clip class has a loop and a stop method. But after you call stop the clip will get closed automatically so don't call start or loop on it after you stopped it.For a machine gun effect you need a delay. You probably have to create another Thread for that. You can communicate with that Thread through a volatile variable.

The clip class has a loop and a stop method. But after you call stop the clip will get closed automatically so don't call start or loop on it after you stopped it.For a machine gun effect you need a delay. You probably have to create another Thread for that. You can communicate with that Thread through a volatile variable.

Why would I need a delay? The sound is played when the fire() method is called on the gun, which already has a cooldown.Anyway, I don't think you get what I'm saying. Whereas most weapons in my game have a cooldown before they can be used again, the Flamethrower just fires particles continuously as long as the player holds down the fire button. The problem being that the sound is played when it's fired, and since it's being looped, that means dozens, or even hundreds, of the Flamethrower sound clip are being created and looped all at once. I tried making it so it wasn't looped and just relied on the fire() event from the weapon to play the sound, but there are A LOT of particles coming out of this thing, so it still sounds like a machine gun of noise on crack. So what I'm asking is... how can I make it so the sound only plays if there is no Flamethrower sound currently being played? The play() method doesn't return the clip that is generated to play the audio, so I can't use that to determine if it's running.

I thought of using a boolean, but how would I determine when the last clip generated by the play() method stops so I can generate a new one?

Wait, so you want to play the flamethrower sound only if it's not playing anymore. Can't you use loop()? Then it will automatically start playing again once it stopped.Also, I edited my previous post. Take a look at the new code.

Wait, so you want to play the flamethrower sound only if it's not playing anymore. Can't you use loop()? Then it will automatically start playing again once it stopped.Also, I edited my previous post. Take a look at the new code.

You're missing the point. I already said that when it was looped, I couldn't stop it because there is no way to stop the Clip once it has been created and started because that Clip only exists in the scope of the play() method in my sounds class. I would need access to that clip in my framework so I can call the stop() method on it under certain conditions. But simply returning the Clip from the play() method wouldn't work because it would return to the weapon class. So unless I made a global variable for the Flamethrower Clip that changed whenever it's played, which I think would be a hacky solution, but a bad idea, I can't get it to stop when the player lets go of the fire button.

Also, forget the "machine gun"... that weapon is not the issue, and works just fine. It's the Flamethrower that's the problem, because there is no delay (or rather, only 20 ms delay) in between creation of each particle, which causes the sound to be played very rapidly, causing the noise in question.

EDIT: Just looked at your modified solution, and that MAY work, but I still feel as if there might be a better option. I'll try it and get back to you.

If there is only a 20ms delay I guess it's best to use loop(). And then call stop(), once the fire button has been released. You can do that by either making the flamethrower AudioData object globally accessible or by adding a MouseListener when the fire button is pressed. You can add as many MouseListeners to your game as you want. That listener will then stop the sound and remove itself.

If there is only a 20ms delay I guess it's best to use loop(). And then call stop(), once the fire button has been released. You can do that by either making the flamethrower AudioData object globally accessible or by adding a MouseListener when the fire button is pressed. You can add as many MouseListeners to your game as you want. That listener will then stop the sound and remove itself.

Haha, oh wow... my new solution works perfectly for the Flamethrower, but now no other sounds will play... will I ever get this right?Here's the code I have now for the play() method in the AudioData class.

Basically, I had a boolean set on each AudioData called active that determines if the sound is currently playing. It's set to true right before the clip starts playing. It then starts the clip and goes into a loop saying "if active, check to see if it's running, and if it's looped. If it's no longer active and isn't looped, set active to false". This ensures that when a clip is finished with playback, it automatically sets active to false and then stops the clip. The looped parameter is provided by the Sounds class. So basically, for normal clips that aren't looped, it sets active to true, then starts a thread in which it constantly checks that clip to see if it's still running. If it's no longer running, active is set to false, and then the clip stops. But for looped clips, like the Flamethrower, it will never set the active boolean to false, meaning it will continue to allow it to loop, never stopping. I then put in the setActive() method to set it to inactive when the mouse is released (among other conditions). So now the Flamethrower starts and stops like it's supposed to, but none of the other clips even play.

What am I doing wrong?

EDIT: Nevermind, I just had to check if the clip was looped and only call stop() if it was looped.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org