简体   繁体   English

如何在 Java 中播放声音?

[英]How can I play sound in Java?

I want to be able to play sound files in my program.我希望能够在我的程序中播放声音文件。 Where should I look?我应该在哪里看?

I wrote the following code that works fine.我编写了以下工作正常的代码。 But I think it only works with .wav format.但我认为它只适用于.wav格式。

public static synchronized void playSound(final String url) {
  new Thread(new Runnable() {
  // The wrapper thread is unnecessary, unless it blocks on the
  // Clip finishing; see comments.
    public void run() {
      try {
        Clip clip = AudioSystem.getClip();
        AudioInputStream inputStream = AudioSystem.getAudioInputStream(
          Main.class.getResourceAsStream("/path/to/sounds/" + url));
        clip.open(inputStream);
        clip.start(); 
      } catch (Exception e) {
        System.err.println(e.getMessage());
      }
    }
  }).start();
}

Java教程的Sound Trail值得作为起点。

A bad example:一个不好的例子:

import  sun.audio.*;    //import the sun.audio package
import  java.io.*;

//** add this into your application code as appropriate
// Open an input stream  to the audio file.
InputStream in = new FileInputStream(Filename);

// Create an AudioStream object from the input stream.
AudioStream as = new AudioStream(in);         

// Use the static class member "player" from class AudioPlayer to play
// clip.
AudioPlayer.player.start(as);            

// Similarly, to stop the audio.
AudioPlayer.player.stop(as); 

I didn't want to have so many lines of code just to play a simple damn sound.我不想有这么多行代码只是为了播放一个简单的该死的声音。 This can work if you have the JavaFX package (already included in my jdk 8).如果您有 JavaFX 包(已经包含在我的 jdk 8 中),这可以工作。

private static void playSound(String sound){
    // cl is the ClassLoader for the current class, ie. CurrentClass.class.getClassLoader();
    URL file = cl.getResource(sound);
    final Media media = new Media(file.toString());
    final MediaPlayer mediaPlayer = new MediaPlayer(media);
    mediaPlayer.play();
}

Notice : You need to initialize JavaFX .注意:您需要初始化 JavaFX A quick way to do that, is to call the constructor of JFXPanel() once in your app :一个快速的方法是在你的应用程序中调用一次 JFXPanel() 的构造函数:

static{
    JFXPanel fxPanel = new JFXPanel();
}

For playing sound in java, you can refer to the following code.在java中播放声音可以参考如下代码。

import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;

// To play sound using Clip, the process need to be alive.
// Hence, we use a Swing application.
public class SoundClipTest extends JFrame {

   public SoundClipTest() {
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.setTitle("Test Sound Clip");
      this.setSize(300, 200);
      this.setVisible(true);

      try {
         // Open an audio input stream.
         URL url = this.getClass().getClassLoader().getResource("gameover.wav");
         AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
         // Get a sound clip resource.
         Clip clip = AudioSystem.getClip();
         // Open audio clip and load samples from the audio input stream.
         clip.open(audioIn);
         clip.start();
      } catch (UnsupportedAudioFileException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (LineUnavailableException e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {
      new SoundClipTest();
   }
}

For whatever reason, the top answer by wchargin was giving me a null pointer error when I was calling this.getClass().getResourceAsStream().无论出于何种原因,当我调用 this.getClass().getResourceAsStream() 时,wchargin 的最佳答案是给了我一个空指针错误。

What worked for me was the following:对我有用的是以下内容:

void playSound(String soundFile) {
    File f = new File("./" + soundFile);
    AudioInputStream audioIn = AudioSystem.getAudioInputStream(f.toURI().toURL());  
    Clip clip = AudioSystem.getClip();
    clip.open(audioIn);
    clip.start();
}

And I would play the sound with:我会播放声音:

 playSound("sounds/effects/sheep1.wav");

sounds/effects/sheep1.wav was located in the base directory of my project in Eclipse (so not inside the src folder). sound/effects/sheep1.wav 位于 Eclipse 中我的项目的基本目录中(所以不在 src 文件夹中)。

I created a game framework sometime ago to work on Android and Desktop, the desktop part that handle sound maybe can be used as inspiration to what you need.前段时间我创建了一个游戏框架,可以在 Android 和桌面上运行,处理声音的桌面部分可能可以作为您需要的灵感。

https://github.com/hamilton-lima/jaga/blob/master/jaga%20desktop/src-desktop/com/athanazio/jaga/desktop/sound/Sound.java https://github.com/hamilton-lima/jaga/blob/master/jaga%20desktop/src-desktop/com/athanazio/jaga/desktop/sound/Sound.java

Here is the code for reference.这是代码供参考。

package com.athanazio.jaga.desktop.sound;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sound {

    AudioInputStream in;

    AudioFormat decodedFormat;

    AudioInputStream din;

    AudioFormat baseFormat;

    SourceDataLine line;

    private boolean loop;

    private BufferedInputStream stream;

    // private ByteArrayInputStream stream;

    /**
     * recreate the stream
     * 
     */
    public void reset() {
        try {
            stream.reset();
            in = AudioSystem.getAudioInputStream(stream);
            din = AudioSystem.getAudioInputStream(decodedFormat, in);
            line = getLine(decodedFormat);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            line.close();
            din.close();
            in.close();
        } catch (IOException e) {
        }
    }

    Sound(String filename, boolean loop) {
        this(filename);
        this.loop = loop;
    }

    Sound(String filename) {
        this.loop = false;
        try {
            InputStream raw = Object.class.getResourceAsStream(filename);
            stream = new BufferedInputStream(raw);

            // ByteArrayOutputStream out = new ByteArrayOutputStream();
            // byte[] buffer = new byte[1024];
            // int read = raw.read(buffer);
            // while( read > 0 ) {
            // out.write(buffer, 0, read);
            // read = raw.read(buffer);
            // }
            // stream = new ByteArrayInputStream(out.toByteArray());

            in = AudioSystem.getAudioInputStream(stream);
            din = null;

            if (in != null) {
                baseFormat = in.getFormat();

                decodedFormat = new AudioFormat(
                        AudioFormat.Encoding.PCM_SIGNED, baseFormat
                                .getSampleRate(), 16, baseFormat.getChannels(),
                        baseFormat.getChannels() * 2, baseFormat
                                .getSampleRate(), false);

                din = AudioSystem.getAudioInputStream(decodedFormat, in);
                line = getLine(decodedFormat);
            }
        } catch (UnsupportedAudioFileException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        }
    }

    private SourceDataLine getLine(AudioFormat audioFormat)
            throws LineUnavailableException {
        SourceDataLine res = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class,
                audioFormat);
        res = (SourceDataLine) AudioSystem.getLine(info);
        res.open(audioFormat);
        return res;
    }

    public void play() {

        try {
            boolean firstTime = true;
            while (firstTime || loop) {

                firstTime = false;
                byte[] data = new byte[4096];

                if (line != null) {

                    line.start();
                    int nBytesRead = 0;

                    while (nBytesRead != -1) {
                        nBytesRead = din.read(data, 0, data.length);
                        if (nBytesRead != -1)
                            line.write(data, 0, nBytesRead);
                    }

                    line.drain();
                    line.stop();
                    line.close();

                    reset();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

There is an alternative to importing the sound files which works in both applets and applications: convert the audio files into .java files and simply use them in your code.导入声音文件的替代方法可以在小程序和应用程序中使用:将音频文件转换为 .java 文件,然后在您的代码中简单地使用它们。

I have developed a tool which makes this process a lot easier.我开发了一个工具,可以让这个过程变得更容易。 It simplifies the Java Sound API quite a bit.它大大简化了 Java Sound API。

http://stephengware.com/projects/soundtoclass/ http://stephenware.com/projects/soundtoclass/

I'm surprised nobody suggested using Applet.我很惊讶没有人建议使用 Applet。 Use Applet .使用Applet You'll have to supply the beep audio file as a wav file, but it works.您必须将哔声音频文件作为wav文件提供,但它可以工作。 I tried this on Ubuntu:我在 Ubuntu 上试过这个:

package javaapplication2;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

public class JavaApplication2 {

    public static void main(String[] args) throws MalformedURLException {
        File file = new File("/path/to/your/sounds/beep3.wav");
        URL url = null;
        if (file.canRead()) {url = file.toURI().toURL();}
        System.out.println(url);
        AudioClip clip = Applet.newAudioClip(url);
        clip.play();
        System.out.println("should've played by now");
    }
}
//beep3.wav was available from: http://www.pacdv.com/sounds/interface_sound_effects/beep-3.wav

It works for me.这个对我有用。 Simple variant简单变体

public void makeSound(){
    File lol = new File("somesound.wav");
    

    try{
        Clip clip = AudioSystem.getClip();
        clip.open(AudioSystem.getAudioInputStream(lol));
        clip.start();
    } catch (Exception e){
        e.printStackTrace();
    }
}

This thread is rather old but I have determined an option that could prove useful.这个线程很旧,但我已经确定了一个可能有用的选项。

Instead of using the Java AudioStream library you could use an external program like Windows Media Player or VLC and run it with a console command through Java.您可以使用 Windows Media Player 或 VLC 等外部程序,并通过 Java 使用控制台命令运行它,而不是使用 Java AudioStream库。

String command = "\"C:/Program Files (x86)/Windows Media Player/wmplayer.exe\" \"C:/song.mp3\"";
try {
    Process p = Runtime.getRuntime().exec(command);
catch (IOException e) {
    e.printStackTrace();
}

This will also create a separate process that can be controlled it the program.这也将创建一个单独的进程,可以控制它的程序。

p.destroy();

Of course this will take longer to execute than using an internal library but there may be programs that can start up faster and possibly without a GUI given certain console commands.当然,这比使用内部库需要更长的时间来执行,但可能有一些程序可以更快地启动,并且可能没有给定某些控制台命令的 GUI。

If time is not of the essence then this is useful.如果时间不是关键,那么这很有用。

I faced many issues to play mp3 file format so converted it to .wav using some online converter我在播放 mp3 文件格式时遇到了很多问题,因此使用一些在线转换器将其转换为 .wav

and then used below code (it was easier instead of mp3 supporting)然后使用下面的代码(它更容易而不是 mp3 支持)

try
{
    Clip clip = AudioSystem.getClip();
    clip.open(AudioSystem.getAudioInputStream(GuiUtils.class.getResource("/sounds/success.wav")));
    clip.start();
}
catch (Exception e)
{
    LogUtils.logError(e);
}
import java.net.URL;
import java.net.MalformedURLException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.IOException;
import java.io.File;
public class SoundClipTest{
    //plays the sound
    public static void playSound(final String path){
        try{
            final File audioFile=new File(path);
            AudioInputStream audioIn=AudioSystem.getAudioInputStream(audioFile);
            Clip clip=AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
            long duration=getDurationInSec(audioIn);
            //System.out.println(duration);
            //We need to delay it otherwise function will return
            //duration is in seconds we are converting it to milliseconds
            Thread.sleep(duration*1000);
        }catch(LineUnavailableException | UnsupportedAudioFileException | MalformedURLException | InterruptedException exception){
            exception.printStackTrace();
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
    }
    //Gives duration in seconds for audio files
    public static long getDurationInSec(final AudioInputStream audioIn){
        final AudioFormat format=audioIn.getFormat();
        double frameRate=format.getFrameRate();
        return (long)(audioIn.getFrameLength()/frameRate);
    }
    ////////main//////
    public static void main(String $[]){
        //SoundClipTest test=new SoundClipTest();
        SoundClipTest.playSound("/home/dev/Downloads/mixkit-sad-game-over-trombone-471.wav");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM