3

编码

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

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

这是什么原因(程序终止且声音未播放)

4

3 回答 3

6

问题是Clip已经启动了一个后台守护线程来播放波形文件。

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

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

最终结果正是您所看到的:当辅助线程启动播放线程时,主线程打印了一些文本,当播放线程开始播放时,繁荣,JVM 结束。有时您甚至可以在 JVM 退出之前从耳机中听到一些“咔哒”声(当声音开始播放时)。

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

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

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

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

我在这个笔记本中找不到我当时写的代码。稍后我将在另一台 PC 上进行检查,如果我找到它,我将发布一个完整的示例(它可以在带有 Sun JVM 的 Windows 和带有 OpenJDK 或 Sun 的 Linux 上可靠地工作)。

于 2011-07-29T10:28:15.987 回答
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());           
 }
}
于 2011-07-29T11:11:55.110 回答
0
while(clip.isRunning()){} 

更好

于 2011-09-30T00:25:47.457 回答