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?
/**
This file is part of Generic Zombie Shooter.
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/>.
**/
package genericzombieshooter.misc;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Contains all pre-loaded sounds.
* @author Darin Beaudreau
*/
public enum Sounds {
// Weapon-Related
POPGUN("shoot2.wav", false),
RTPS("shoot1.wav", false),
BOOMSTICK("shotgun1.wav", false),
FLAMETHROWER("flamethrower.wav", true),
THROW("throw2.wav", false),
EXPLOSION("explosion2.wav", false),
LANDMINE_ARMED("landmine_armed.wav", false),
TELEPORT("teleport.wav", false),
// Zombie-Related
MOAN1("zombie_moan_01.wav", false),
MOAN2("zombie_moan_02.wav", false),
MOAN3("zombie_moan_03.wav", false),
MOAN4("zombie_moan_04.wav", false),
MOAN5("zombie_moan_05.wav", false),
MOAN6("zombie_moan_06.wav", false),
MOAN7("zombie_moan_07.wav", false),
MOAN8("zombie_moan_08.wav", false),
POISONCLOUD("poison_cloud.wav", false),
// Game Sounds
POWERUP("powerup.wav", false),
PURCHASEWEAPON("purchase_weapon.wav", false),
BUYAMMO("buy_ammo2.wav", false),
POINTBUY("point_buy.wav", false),
PAUSE("pause.wav", false),
UNPAUSE("unpause.wav", false);
private Clip clip;
private boolean looped;
Sounds(String filename, boolean loop) {
openClip(filename, loop);
}
private synchronized void openClip(String filename, boolean loop) {
try {
URL audioFile = Sounds.class.getResource("/resources/sounds/" + filename);
AudioInputStream audio = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audio.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(audio);
} catch (UnsupportedAudioFileException uae) {
System.out.println(uae);
} catch (IOException ioe) {
System.out.println(ioe);
} catch (LineUnavailableException lue) {
System.out.println(lue);
}
looped = loop;
}
public synchronized void play() {
play(1.0);
}
public synchronized void play(final double gain) {
Runnable soundPlay = new Runnable() {
@Override
public void run() {
Clip clipCopy = (Clip)clip;
FloatControl gainControl = (FloatControl)clipCopy.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float)(Math.log(gain) / Math.log(10.0) * 20.0);
gainControl.setValue(dB);
if(!looped) reset(clipCopy);
clipCopy.loop((looped)?Clip.LOOP_CONTINUOUSLY:0);
}
};
new Thread(soundPlay).start();
}
public synchronized void reset() {
reset(clip);
}
public synchronized void reset(Clip clipCopy) {
clipCopy.setFramePosition(0);
}
public static void init() {
values();
}
}
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?