为啥这段代码不播放声音文件
Posted
技术标签:
【中文标题】为啥这段代码不播放声音文件【英文标题】:why this code doesn't play the sound file为什么这段代码不播放声音文件 【发布时间】:2011-07-29 08:55:55 【问题描述】:代码
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);
这段代码确实提供了输出 sound thread working ,但不播放任何东西。在这段代码中,我已经启动了一个单独的线程来播放声音,并且在声音线程完成它的工作之前程序不应该终止。但是程序在打印一系列声音线程工作后终止。
这是什么原因(程序终止,声音不播放)?
【问题讨论】:
我的意思是编辑你的other question。但是我在那里制作的相同 cmets 在这里适用。链接源中的最后两个单行 cmets 对您意味着什么? @Andrew Thompson 这意味着程序只有在由clip
生成的守护线程完成后才会终止。但我不知道为什么它会在播放 3-4 秒后结束。
@ Andrew Thompson JOptionPane
出现一段时间后自行消失。我之前发布过这个问题,但没有得到任何有意义的答案***.com/questions/6594921/…
"JOptionPane
出现一段时间后自行消失。" 我能想到的唯一一件事就是“您的 Java 安装已损坏”。
@Andrew Thompson 你说的坏了是什么意思
【参考方案1】:
问题是Clip
已经启动了一个后台daemon线程来播放波形文件。
所以,你的代码的执行流程如下:
主线程启动辅助(无用)线程 辅助线程启动一个守护线程(它将播放声音) 与此同时,主线程在辅助线程处于活动状态时继续打印一些内容 当辅助线程完成启动播放线程时,它会结束,因此辅助线程将不再处于活动状态 主线程会注意到辅助线程处于非活动状态并且也会结束 由于播放线程是一个守护线程,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 上可靠地工作)。
【讨论】:
我得到了504845
的帧长度我怎么知道它的轨道长度?
这是我不记得的确切内容...我必须检查我的代码才能确定。但是您可以尝试clip.getFormat().getFrameRate()
之类的方法,它应该为您提供每秒的帧数(通常这个值在 8000 到 44100 之间)。然后将帧数 (getFrameLength()) 除以帧速率,得到剪辑的长度(以秒为单位)。【参考方案2】:
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());
【讨论】:
我会删除try catch
块并只留下Thread.sleep(...)
,因为在这样一个简单的代码中没有必要(您甚至将main
方法声明为throws Exception
) ,而在生产代码中,这与处理InterruptedException
的正确方法相去甚远。【参考方案3】:
while(clip.isRunning())
更好
【讨论】:
如果我通过clip.stop()
停止/暂停了该行并且主线程完成了它的工作,该怎么办。它将返回true
,我将被排除在程序之外。我认为这张支票不符合条件。以上是关于为啥这段代码不播放声音文件的主要内容,如果未能解决你的问题,请参考以下文章