Java Sound Repeated Play - java

I'm trying to add sound to a game I've been working on, and I'm having trouble getting the sounds to play more than once. I think I've worked out the cause, but I'm not sure how to solve it. I'm using an enumerator I found while searching for a Java sound tutorial.
The problem is that I'm calling the sound within a thread, in my update() method, and that each time I call the play() method of the sound, it starts the clip over. The first time it's called, the sound plays fine (I may get a bit of a freeze), but all attempts afterwards to play the sound fail. I don't get any exceptions or errors, the sound just doesn't play.
public enum Sounds {
RIFLE("rifle_fire.wav");
private Clip clip;
Sounds(String filename) {
openClip(filename);
}
public synchronized void openClip(String filename) {
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);
}
}
public synchronized void play() {
if(clip.isRunning()) clip.stop();
clip.setFramePosition(0);
clip.start();
}
public static void init() {
values();
}
}
That is the enumerator I use. It's called from the update() method of my main thread, which is updated every 20 ms. In the update method, I call it like this.
// If the left mouse button is held down, create a new projectile.
if(Globals.buttons[0] && !player.isOnCooldown()) {
createParticle(pAngle);
Sounds.RIFLE.play();
}
Someone suggested I need to close the line after using it, but the sound is only opened once... why would I need to close it? Anyone know what the problem is?

Related

Needing to type full path to save file?

Okay, this is my first post here, sorry if i did something wrong. (please let me know if i did aswell)
So i've been trying to make a "data" folder with a audio(.wav) file in it when the runnable jar file is run but for some reason it doesn't work, i've tried to get this working for the last week but i finally kinda gave up on trying to get it working without help(other than searching around the internet) and therefore ask here.
So i have this code:
public static void loop(String path, int volume) {
try {
if (volume > 6) throw new IllegalArgumentException("Requested volume ("+volume+") is higher than allowed. (maximum 6)");
else if (volume < -80) throw new IllegalArgumentException("Requested volume ("+volume+") is lower than allowed. (minimum -80)");
else {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File(path)));
clip.loop(Clip.LOOP_CONTINUOUSLY);
FloatControl gain = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gain.setValue(volume);
clip.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
for looping a .wav file continuously and it works, then i try to save the file with this code:
public void save(String music, String output) {
try {
File sound = new File(music);
AudioInputStream ais = AudioSystem.getAudioInputStream(sound);
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File(output));
} catch (IOException | UnsupportedAudioFileException e) {
e.printStackTrace();
}
}
And that seems to work aswell when i do something like this:
save("D:\\Eclipse\\eclipse\\workspace\\Test\\data\\music.wav", "C:\\Users\\Karim\\Desktop\\data\\test.wav");
loop("C:\\Users\\Karim\\Desktop\\data\\test.wav", -30);
But if i try to do this instead:
private File jar() {
try {
File jar = new File(Game.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
return jar;
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
private File data = new File(jar().getParentFile().getPath()+File.separator+"\\data");
private File music = new File(data.getPath()+"\\music.wav");
save(music.getPath(), "C:\\Users\\Karim\\Desktop\\data\\test.wav");
loop("C:\\Users\\Karim\\Desktop\\data\\test.wav", -30);
it won't save the file, why is that and what can i do to make it save?
Final Notes:
I'm pretty new to java.
I'm pretty new to programming in itself.
I don't want to use a library, i wanna try to make it work without and i'm so close.
If i forgot to say anything please let me know and i'll edit this post or make a comment.
EDIT: Just wanted to make it clear that this works in the IDE but not when i export it. Also i have the data folder both IN the 'src' folder and beside the 'src' folder, just for testing.

getting lag when loading and playing sounds

i wrote a little sound class where i can make a sound and toggle it and stuff but im not too great and i had to at least temporarily scrap it. i tried a little method to load sound and play it and then when it ends to unload it. it causes a lot of lag though. the class i had before would do the same thing as far as i can see but it didnt discard the sound properly and the soundswouldnt load anymore. heres my method thats causing ober lag but is working for what it should do. i need help refining it please.
public static void runOnce(final String location) {
try {
File audioFile = new File(Game.gameFolder + "/sounds/" + location);
final AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
final Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.start();
new Thread(new Runnable() {
public void run() {
while (audioClip.isActive()) {}
try {
audioClip.close();
audioStream.close();
} catch (Exception e) {}
}
}).start();
} catch (Exception e) {}
}

No sound after export to jar

I have problem with my app. When I run app in Eclipse, sound played well, but if I export app to runnable jar, sound doesn't work.
Method, where sound is played:
public static synchronized void playSound()
{
new Thread(new Runnable()
{
// The wrapper thread is unnecessary, unless it blocks on the
// Clip finishing; see comments.
public void run()
{
try
{
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(getClass().getResourceAsStream("sound.wav"));
clip = AudioSystem.getClip();
clip.open(inputStream);
clip.start();
}
catch (Exception e)
{
System.err.println(e.getMessage());
}
}
}).start();
}
Where can be a mistake?
The problem is in this
AudioInputStream inputStream = AudioSystem.getAudioInputStream(getClass().getResourceAsStream("sound.wav"));
in JAR file isn't working getResourceAsStream for any reason. So I replace it with getResource:
AudioInputStream inputStream = AudioSystem.getAudioInputStream(getClass().getResource("sound.wav"));
and this works fine.

Java application hangs on AudioClip.stop() [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm writing a videogame and I want to stop the music when a player loses or quits (to the main menu).
Here's my code:
public class Music{
private static Clip clip;
private static AudioInputStream stream;
private static void loadMusic(){
if(clip != null) return;
try {
AudioFormat format;
DataLine.Info info;
stream = AudioSystem.getAudioInputStream(Music.class.getResource("/resources/music/music.wav"));
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void playMusic(boolean loop){
loadMusic();
if(clip == null) return;
if(loop) clip.loop(Clip.LOOP_CONTINUOUSLY);
else clip.start();
}
public static void stopMusic(){
clip.stop();
clip.setMicrosecondPosition(0);
}
}
Whenever I call Music.stopMusic(), the game hangs for a few seconds then continues.
From what i gather form your description, you are pressing a stop button on your GUI and this calls Music.stopMusic(). The result is that the audio clip stops playing, but you are still waiting 3 seconds before you GUI becomes responsive.
This is because the call you are making in Music.stopMusic() makes native calls to I/O resources, and this should not be called in the EDT. You should look at running up a worker thread to do this:
Thread t = new Thread(new Runnable() {
public void run() {
Music.stop();
}
});
t.start();
Or look to using a SwingWorker.
Interestingly, though I am not sure which implementation of Clip is returned, but a quick look at MixerClip shows a call to a native library, and then perhaps the smoking gun in your predicament- a 3 second wait for a callback!
// stop the sample. this invalidates the sample voice id.
nStop(id);
// wait for the callback
synchronized(lock) {
if (id!=0) {
try {
//long time=System.currentTimeMillis();
lock.wait(3000);
//if (System.currentTimeMillis()-time > 2500) {
//System.out.println(" WAITING TIMED OUT!"); System.out.flush();
//id=0;
//}
} catch (InterruptedException e) { }
}
}

javax.sound.sampled how does it work?

I am trying to play a sound in Java.
So far it is going well, thank you, but I have a problem understanding how does this work.
I wrote a function that does the playback:
private static void PlaySound(String path) {
try {
final File SoundFile = new File(path);
AudioInputStream Sound = AudioSystem.getAudioInputStream(SoundFile);
DataLine.Info info = new DataLine.Info(Clip.class, Sound.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(Sound);
clip.addLineListener(new LineListener() {
public void update (LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
event.getLine().close();
System.out.printf("Playback ended!");
System.exit(0);
}
}
});
System.out.printf("This sound is %f seconds long.", (clip.getMicrosecondLength() / 1000.0d));
clip.start();
} catch (Exception e) {
ErrorHandler(e);
}
}
Now this function works almost fine: when the sound has ended, it calls the event.getLine().close(); function, but it is stuck in an "infinite loop" (not sure if it is) and nothing after that statement gets executed, and the program runs until I kill it manually.
If I change the line
if (event.getType() == LineEvent.Type.STOP) {
to
if (event.getType() == LineEvent.Type.CLOSE) {
then the sound plays, and the program exits correctly, but still none of the statement after the event.getLine().close(); are executed.
The question is: is this the intended behavior of event.getLine().close(), or I am doing something wrong?
Solution:
The LineListener is actually based on an outdated fact, that Java Sound has a bug in it, and we need to exit explicitly from the vm. Without the listener, the code just works fine.
See if it's raising an exception:
public void update (LineEvent event) {
if (event.getType().equals(LineEvent.Type.STOP)) {
try {
event.getLine().close();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.printf("Playback ended!");
}
}

Categories