为什么这段代码不播放声音文件

时间:2011-07-29 08:55:56

标签: java multithreading audio javasound

代码

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);
     }       
 }
}

此代码确实输出声音线程正常,但不播放任何内容。在这段代码中,我已经启动了一个单独的线程来播放声音,程序不应该终止,直到声音线程完成它的工作。但程序在打印声音线程工作系列后终止。

这个的原因是什么(程序终止和声音没有播放)

3 个答案:

答案 0 :(得分:6)

问题是Clip已经启动了后台 守护程序 线程来播放wave文件。

因此,代码的执行流程如下:

  • 主线程启动辅助(无用)线程
  • 辅助线程启动守护程序线程(将播放声音)
  • 同时,主线程在辅助线程处于活动状态时继续打印
  • 当辅助线程完成启动回放线程时,它将结束,因此辅助线程将不再处于活动状态
  • 主线程会注意到辅助线程未激活并且也将结束
  • 由于回放线程是守护程序线程,JVM将退出(因为只留下的线程是守护程序线程)

最终的结果正是你所看到的:当辅助线程启动播放线程时,主线程会打印一些文本,当播放线程开始播放时,JVM就会完成。有时你甚至可以在JVM退出之前从耳机中听到一些“点击”(当声音开始播放时)。

最简单的解决方法是在播放声音时让辅助线程(即非守护程序线程)休眠。

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

需要注意的一件重要事情:大约1年前,当我使用该java API时,我注意到方法getMicrosecondLength()是错误的。我在Windows和Linux上编码,在一个平台上我得到了正确的值,但在另一个平台上,同样的方法会以毫秒为单位返回长度!

我发现获得声音实际长度的最可靠方法是使用getFrameLength()方法,并从中计算长度。

我找不到我在这个笔记本上写的代码。我将在稍后的另一台PC上查看,如果我发现它,我将发布一个完整的示例(在使用Sun JVM和Linux的Windows上使用OpenJDK或Sun可靠地运行。)

答案 1 :(得分:0)

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());           
 }
}

答案 2 :(得分:0)

while(clip.isRunning()){} 

更好