Why this code does not play a 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(); } }; 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 gives an output sound stream , but does not play anything. In this code, I started a separate thread for playing sound, and the program should not end until the sound thread finishes its work. But the program stops working after printing a series of audio threads working .

What is the reason for this (to end the program and the lack of sound)?

+3
source share
3 answers

The problem is that Clip already starting the daemon stream to play the wave file.

So, the flow of execution of your code is as follows:

  • the main thread starts a secondary (useless) thread
  • secondary stream starts the daemon stream (which will play the sound)
  • at the same time, the main stream continues to print something, while the secondary stream exists
  • When the secondary stream finishes launching the playback stream, it ends, so the secondary stream will no longer be in the active state
  • the main thread will notice that the secondary thread is inactive and will also end.
  • Since the playback thread is a daemon thread, the JVM will exit (because only the remaining threads are daemon threads).

The end result is exactly what you see: some text is printed by the main stream, while the secondary stream starts the play thread, and when the play thread starts playing, the arrow, the JVM ends. Sometimes you can even hear a β€œclick” from the headphones (as the sound starts to play) before the JVM comes out.

The simplest fix is ​​that a secondary stream (i.e., a non-daemon stream) occurs during sound playback from outside.

 ... clip.open(ais); clip.loop(-1); Thread.sleep(amountToSleep); ... 

It is important to note : about 1 year ago, when I was working with this Java API, I noticed that the getMicrosecondLength() method is an error. I encoded on both Windows and Linux, and on one platform I got the correct value, but on another, the same method would return the length in milliseconds!

I found that the most reliable way to get the actual length of the sound is to use the getFrameLength() method and calculate the length from it.

I could not find the code that I wrote then on this laptop. I will check later on another PC, and if I find it, I will post a complete example (which works reliably with both Windows with Sun JVM and Linux with OpenJDK or Sun).

+6
source
 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()); } } 
0
source
 while(clip.isRunning()){} 

it's better

0
source

Source: https://habr.com/ru/post/893804/


All Articles