如何在java中播放声音?

时间:2014-12-03 23:37:43

标签: java audio

我正在设计一个简单的计时器应用程序,但我在播放声音方面遇到了一些麻烦。

这是我的代码

public class Timer {

    private static int time = 0;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("Type the values");
        System.out.print("Hours   :  ");
        int hours = scanner.nextInt();
        System.out.print("Minutes :  ");
        int minutes = scanner.nextInt();
        System.out.print("Seconds :  ");
        int seconds = scanner.nextInt();

        time = hours * 3600 + minutes * 60 + seconds;

        new Thread() {
            @Override
            public void run() {
                try {
                    while (time != 0) {
                        time--;
                        sleep(1000);
                    }
                    System.out.println("Time elapsed");
                    URL url = Timer.class.getResource("Timer.wav");
                    AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
                    Clip clip = AudioSystem.getClip();
                    clip.open(audioIn);
                    clip.start();
                } catch (InterruptedException | UnsupportedAudioFileException | IOException | LineUnavailableException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        System.out.println("Timer started");

    }
}

这是我的项目结构。 enter image description here 现在问题是应用程序没有给我任何异常,虽然它不播放声音。怎么了?

4 个答案:

答案 0 :(得分:3)

这实际上是一个多线程问题。

问题是你开始剪辑,但是然后终止你的程序而没有让它有机会玩它结束。 Clip.start()方法不是阻塞操作,这意味着它不会等待,而是启动一个新的守护程序线程来播放声音,这是一个守护程序线程,一旦程序退出main方法就会被杀死。

以下是我other answer的代码示例,用于使用Clip播放音频文件。请注意我计算声音持续时间的方式,然后sleep()让它播放。

import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class PlaySound {
    private static boolean tryToInterruptSound = false;
    private static long mainTimeOut = 3000;
    private static long startTime = System.currentTimeMillis();

    public static synchronized Thread playSound(final File file) {

        Thread soundThread = new Thread() {
            @Override
            public void run() {
                try{
                    Clip clip = null;
                    AudioInputStream inputStream = null;
                    clip = AudioSystem.getClip();
                    inputStream = AudioSystem.getAudioInputStream(file);
                    AudioFormat format = inputStream.getFormat();
                    long audioFileLength = file.length();
                    int frameSize = format.getFrameSize();
                    float frameRate = format.getFrameRate();
                    long durationInMiliSeconds = 
                            (long) (((float)audioFileLength / (frameSize * frameRate)) * 1000);

                    clip.open(inputStream);
                    clip.start();
                    System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound started playing!");
                    Thread.sleep(durationInMiliSeconds);
                    while (true) {
                        if (!clip.isActive()) {
                            System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound got to it's end!");
                            break;
                        }
                        long fPos = (long)(clip.getMicrosecondPosition() / 1000);
                        long left = durationInMiliSeconds - fPos;
                        System.out.println("" + (System.currentTimeMillis() - startTime) + ": time left: " + left);
                        if (left > 0) Thread.sleep(left);
                    }
                    clip.stop();  
                    System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound stoped");
                    clip.close();
                    inputStream.close();
                } catch (LineUnavailableException e) {
                    e.printStackTrace();
                } catch (UnsupportedAudioFileException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    System.out.println("" + (System.currentTimeMillis() - startTime) + ": sound interrupted while playing.");
                }
            }
        };
        soundThread.setDaemon(true);
        soundThread.start();
        return soundThread;
    }

    public static void main(String[] args) {
        Thread soundThread = playSound(new File("C:\\Booboo.wav"));
        System.out.println("" + (System.currentTimeMillis() - startTime) + ": playSound returned, keep running the code");
        try {   
            Thread.sleep(mainTimeOut );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (tryToInterruptSound) {
            try {   
                soundThread.interrupt();
                Thread.sleep(1); 
                // Sleep in order to let the interruption handling end before
                // exiting the program (else the interruption could be handled
                // after the main thread ends!).
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("" + (System.currentTimeMillis() - startTime) + ": End of main thread; exiting program " + 
                (soundThread.isAlive() ? "killing the sound deamon thread" : ""));
    }
}

答案 1 :(得分:1)

问题是在剪辑开始播放之前应用程序退出了。 所以我用这个新游戏替换了我的游戏块。

                URL url = Timer.class.getResource("Timer.wav");
                AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
                AudioFormat format = audioIn.getFormat();
                Clip clip = AudioSystem.getClip();
                clip.open(audioIn);
                clip.start();
                long frames = audioIn.getFrameLength();
                double durationInSeconds = (frames + 0.0) / format.getFrameRate();
                sleep((long) durationInSeconds * 1000);

现在等到剪辑播放完成,然后应用程序才完成它的工作

答案 2 :(得分:0)

编辑:如果我在发布答案之前阅读整个代码可能会有所帮助。好的,你的class.getResource(“Timer.wav”)实际上应该是class.getResource(“resources / Timer.wav”)我假设资源是你的类结构中的一个文件夹。此外,如果您使用getResourceAsStream而不是getResource,则可以跳过URL事物。

答案 3 :(得分:0)

您应该测试以查看资源是否实际成功检索到了:

URL url = Timer.class.getResource("Timer.wav");
if (url == null)
{
    System.out.println("wav file resource not found!");
    return;
}
// continue on

还要在程序中添加一个未捕获的异常处理程序,以查看是否有任何异常一直转移到程序顶部:

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler()
{
    public void uncaughtException(Thread t, Throwable e)
    {
        String msg = "DefaultUncaughtExceptionHandler thread[" + t.getName() + "]";
        System.out.println(msg);
        e.printStackTrace(System.out);
        System.err.println(msg);
        e.printStackTrace(System.err);
    }
});