why this code doesn't play the sound file
The code
import javax.sound.sampled.*;
import java.io.*;
public class Tester {
static Thread th;
public static void main(String[] args) {
startNewThread();
while( th.isAlive() == true) {
System.out.println("sound thread is working");
}
}
public static void startNewThread() {
Runnable r = new Runnable() {
public void run() {
startPlaying();
}
};
开发者_如何学C th =new Thread(r);
th.start();
}
public static void startPlaying() {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.loop(-1); // keep playing the sound
} catch(Exception exc) {
System.out.println(exc);
}
}
}
This code does give the output sound thread working , but does not play anything. In this code i have started a separate thread for playing sound and the program should not terminate till the sound thread has finished it's job .But the program terminates after printing series of sound thread working.
What is the reason for this ( for the program terminating and the sound not playing) ?
The problem is that Clip
already launches a background daemon thread to play the wave file.
So, the execution flow of your code is as follows:
- the main thread launches a secondary (useless) thread
- the secondary thread launches a daemon thread (which will play the sound)
- in the mean time, the main thread keeps printing something while the secondary thread is alive
- When the secondary thread finishes launching the playback thread, it will end, so the secondary thread will not be in the active state anymore
- the main thread will notice that the secondary thread is not active and will end as well
- Since the playback thread is a daemon thread, the JVM will exit (because the only threads left are daemon threads)
The final result is precisely what you see: some text get printed by the main thread while the secondary thread is launching the playback thread, and when the playback thread would start playing, boom, the JVM finishes. Sometimes you might even be able to listen some "clicking" from the headphones (as the sound starts to play) before the JVM exits.
The easiest fix is to make the secondary thread (ie, a non-daemon thread) sleep while the sound is playing.
...
clip.open(ais);
clip.loop(-1);
Thread.sleep(amountToSleep);
...
One important thing to notice: about 1 year ago, when I worked with that java API, I noticed that the method getMicrosecondLength()
is buggy. I was coding both in Windows and Linux, and in one platform I'd get the correct value, but in the other, the very same method would return the length in milliseconds!
I found that the most reliable way to get the real length of the sound is to use the getFrameLength()
method, and calculate the length from that.
I couldn't locate the code I wrote back then in this notebook. I will check later in another PC, and if I find it I will post a complete example (that works reliably on both Windows with Sun JVM and Linux with either OpenJDK or Sun).
import javax.sound.sampled.*;
import java.io.*;
import javax.swing.*;
public class Tester {
static Thread th;
public static void main(String[] args) throws Exception {
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
clip.open(ais);
clip.loop(0);
// Calculate totalFrames
long totalFrames = (long)(clip.getFrameLength() * clip.getFormat().getFrameRate());
Thread.sleep( ( totalFrames* 1000 )); // pause the thread till the sound plays
System.out.println(clip.getFrameLength());
System.out.println(clip.getFormat().getFrameRate());
}
}
while(clip.isRunning()){}
is better
精彩评论