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!");
}
}
Related
I'm trying to move a file after its being played.
I'm using javazoom's basicplayer to play my files and I tried
player.close();
controler.close();
and DSP.close();
and none work
Here is the code I use to play the file
public void play(File sound) {
if (sound.exists()) {
new Thread("Sound player") {
public void run() {
currentSelectedSound = sound;
try {
control.open(currentSelectedSound);
control.play();
setVolume(currentAudioVolume);
setPan(currentAudioPan);
} catch (BasicPlayerException e) {
e.printStackTrace();
System.err.println("Error!");
}
}
}.start();
} else {
Logger.logError(TAG, "File doesn't exist!");
}
}
I'm so happy it finally works, heres the answer for anyone :
stop();
try {
//The thread used to play() the sound
soundPlayThread.join();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
//Manually run the garbage collection and yield threads
System.gc();
Thread.yield();
I hope no one wastes 6 hours like I just did
Extreme big thanks to wuppi
https://stackoverflow.com/a/14123384/3224295
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) {}
}
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.
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?
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) { }
}
}