【问题标题】:How can I play sound in Java?如何在 Java 中播放声音?
【发布时间】:2010-09-06 18:42:43
【问题描述】:

我希望能够在我的程序中播放声音文件。我应该去哪里看?

【问题讨论】:

标签: java audio


【解决方案1】:

我编写了以下运行良好的代码。但我认为它只适用于.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();
}

【讨论】:

  • 为避免 Clip 随机关闭,需要 LineListener。看看:stackoverflow.com/questions/577724/trouble-playing-wav-in-java/…
  • +1 表示使用公共 API 的解决方案。但是创建一个新线程不是不必要(冗余)吗?
  • 谢谢.. 是多余的吗?我把它变成了一个新线程,这样我就可以在第一个剪辑结束之前再次播放声音。
  • 我知道 clip.start() 会产生一个新线程,所以我很确定它是不必要的。
  • 1) Thread 是不必要的。 2) 有关使用Clip 的一个很好的例子,请参阅JavaSound info. page。 3) 如果一个方法需要一个URL(或File)给它一个dang URL(或File),而不是接受一个代表一个的String。 (只是个人的“我的帽子里的蜜蜂”。) 4)e.printStackTrace();System.err.println(e.getMessage()); 提供更多信息,输入更少。
【解决方案2】:

一个不好的例子:

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

【讨论】:

  • java.sun.com/products/jdk/faq/faq-sun-packages.html 有使用 sun.audio 的公共 API 替代方案。
  • @GregHurlman 不是 sun.* 包不被我们开发人员使用吗?
  • 这个例子来自 1997 JavaWorld 的一篇文章。过时了,你不应该使用 sun.* 包。
  • 您是否需要关闭“in”?
  • +1 not 使用 sun.* 包。他们有一些奇怪的错误,比如不处理大于 1MB 的文件,如果前一个剪辑尚未完成,则无法播放一个剪辑,等等。
【解决方案3】:

我不想为了播放一个简单的该死的声音而编写这么多行代码。如果你有 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();
}

注意:您需要initialize JavaFX。一种快速的方法是在您的应用程序中调用 JFXPanel() 的构造函数:

static{
    JFXPanel fxPanel = new JFXPanel();
}

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      无论出于何种原因,当我调用 this.getClass().getResourceAsStream() 时,wchargin 的最佳答案是给我一个空指针错误。

      对我有用的是:

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

      我会用以下方式播放声音:

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

      sounds/effects/sheep1.wav 位于我在 Eclipse 中项目的基本目录中(因此不在 src 文件夹中)。

      【讨论】:

      • 你好 Anrew,你的代码对我有用,但我注意到执行需要一些额外的时间......大约 1.5 秒。
      • getResourceAsStream() 如果找不到资源,将返回 null,如果 namenull,则抛出异常 - 如果给定路径无效,则不是最佳答案的错误
      【解决方案6】:

      我前段时间创建了一个游戏框架,用于 Android 和桌面,处理声音的桌面部分也许可以作为你需要的灵感。

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

      这是代码供参考。

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

      【讨论】:

      • 此代码可能在stream.reset(); 上出错,导致Resetting to invalid mark。您打算如何解决这个问题?
      • 也许重新创建流,见stackoverflow.com/questions/18573767/…
      • 我实际上是在初始化raw 之后使用raw.mark(raw.available()+1) 解决了这个问题,然后在while 循环中使用raw.reset() 而不是stream.reset()。我现在的问题是,当要重置时,播放之间存在间隙。我想实现像Clip 那样的连续循环。我没有使用Clip,因为操纵诸如 MASTER_GAIN 之类的控件有大约 500 毫秒的明显延迟。这可能应该是它自己的问题,我稍后会问。
      • 不是do { ... } while?
      【解决方案7】:

      除了导入适用于小程序和应用程序的声音文件之外,还有另一种方法:将音频文件转换为 .java 文件,然后在您的代码中简单地使用它们。

      我开发了一个工具,可以让这个过程变得更容易。它大大简化了 Java Sound API。

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

      【讨论】:

      • 我使用您的系统从 wav 文件创建一个类,但是,当我执行 my_wave.play();它不播放音频..我需要初始化音频系统吗?..
      • 如果它确实有效,那将是非常酷的。运行play()时,获取Audio Line失败(异常“java.lang.IllegalArgumentException: No line matching interface SourceDataLine support format PCM_UNSIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian is supported.” 不是抛出)。伤心。
      【解决方案8】:

      我很惊讶没有人建议使用 Applet。 UseApplet。您必须将哔声音频文件作为wav 文件提供,但它可以工作。我在 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
      

      【讨论】:

      • Applet 自 Java 9 起已弃用。
      【解决方案9】:

      它对我有用。简单变体

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

      【讨论】:

        【解决方案10】:

        这个帖子比较老了,但我已经确定了一个可能有用的选项。

        您可以使用 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();
        }
        

        这也将创建一个可以控制它的程序的单独进程。

        p.destroy();
        

        当然,与使用内部库相比,这将花费更长的时间来执行,但在某些控制台命令的情况下,可能有一些程序可以更快地启动并且可能没有 GUI。

        如果时间不是最重要的,那么这很有用。

        【讨论】:

        • 虽然我认为这是一个客观上糟糕的解决方案(在可靠性、效率和其他此类指标方面),但它至少是一个我不会想到的有趣的解决方案!
        【解决方案11】:

        我在播放 mp3 文件格式时遇到了很多问题 所以使用一些online converter将其转换为.wav

        然后在下面的代码中使用(它更容易而不是支持 mp3)

        try
        {
            Clip clip = AudioSystem.getClip();
            clip.open(AudioSystem.getAudioInputStream(GuiUtils.class.getResource("/sounds/success.wav")));
            clip.start();
        }
        catch (Exception e)
        {
            LogUtils.logError(e);
        }
        

        【讨论】:

          【解决方案12】:
          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");
              }
          }
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          • 1970-01-01
          • 1970-01-01
          • 2012-06-21
          • 2013-12-10
          • 1970-01-01
          • 2011-12-04
          相关资源
          最近更新 更多