Java应用程序如何播放声音片段?

时间:2011-06-17 16:55:11

标签: java audio clip javasound

以下是我见过的最可能解释的链接,但我仍有疑问。

How can I play sound in Java?

我会在这里引用代码:

public static synchronized void playSound(final String url) {
new Thread(new Runnable() {
  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();

}

  1. 这是否适用于应用程序,而不是Applet?
  2. 方法Main.class.getResourceAsStream()似乎需要 import com.sun.tools.apt.Main; 但我找不到相关文档,我不知道它是做什么的。例如,“/ path / to / sounds /”是绝对的还是相对的,如果是后者,则相对于哪里?
  3. 我现在花了很多时间尝试播放简单的音效。令人难以置信的是它有多难。我希望上面的代码可以工作。谢谢你的帮助。

3 个答案:

答案 0 :(得分:1)

  

这是否适用于应用程序,而不是Applet?

它适用于任何一种。

  

方法Main.class.getResourceAsStream()似乎需要导入com.sun.tools.apt.Main;

你从哪里得到这个想法?我已经做了很多声音的例子,从未听说过你不应该使用的那个课程。

  

..但我找不到相关的文档,..

不,com.sun类不仅没有文档,而且可能会在下一个微版本中发生变化。

  

..我不知道它的作用。例如,“/ path / to / sounds /”是绝对的还是相对的,如果是后者,相对于哪里?

它相对于类路径的根。

  

..令人难以置信的是它有多难。

一般来说,媒体处理很棘手。


BTW - 我对链接线程上的代码印象不深。 Thread包装 是不必要的,正如在几条评论中所提到的,即使是同时播放多个Clip个实例也是如此。

请参阅我(写作&)亲自推荐的this code

答案 1 :(得分:1)

  1. 这应该适用于应用程序。
  2. 这行代码最有可能引用方法所在的类。所以该方法最初是在Main类中,如果将该方法放在类FooBar中,则应将其更改为FooBar.class.getResourceAsStream()。 / LI>
  3. 这是一条相对路径。它将在每个包之外寻找资源。示例:假设运行此代码的类位于C:\ Users \ Jeffrey \ bin \ foo \ bar \ SoundPlayer.class,类位于包foo.bar中。这意味着ClassLoader将在C:\ Users \ Jeffrey \ bin \文件夹中查找资源。 (在您的情况下,它将在C:\ Users \ Jeffrey \ bin \ path \ to \ sounds \ + url中查找资源)
  4. 我总是加载这样的声音:

     Clip sound = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
     sound.open(AudioSystem.getAudioInputStream(file));
    

    但你的方法也应该有用。

答案 2 :(得分:0)

虽然我从@ Andrew的代码中大量使用,但我确实需要在这里和那里做一些调整。以下是我的解决方案的演示,除了示例.wav文件外完整。

// Developed in Eclipse, YMMV regarding resource location.
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

class ClipPlayer {

public static void main(String[] args) {
    // First, instantiate ourselves so we can call demoSam which
    // needs to be able to do a wait().
    ClipPlayer cp = new ClipPlayer();
    // Now run the actual demo
    cp.demoSam();
}

private void demoSam() {

    /**
     * Construct a Sam, capable of playing the "Chook.wav", a 0.1 sec sound.
     * NOTE: it's very tricky debugging an incorrectly-located
     * resource file, and I'm unable to give a general rule
     * here.  But in this example, Chook.wav is expected to be in the same
     * directory as the .class file, and there is no surrounding
     * package (i.e. we're taking the default package name).  If you
     * are using a package, you may have to write "myPackage/Chook.wav"
     * instead.
     */

    Sam sam;
    try {
        sam = new Sam("Chook.wav"); // or whatever, but it has to be .wav
    }
    catch (Exception e) {
        say("Exception thrown by Sam: " + e.getMessage());
        System.exit(1); // scoot
        return; // get rid of warning about sam possib not init'd
    }
    int countDown = 20;
    do {
        say("Doing something requiring accompanying sound effect...");
        try {
            sam.playIt();
        }
        catch (Exception e) {
            say("Caught exception from playIt: " + e.getMessage());
            System.exit(1);
        }

        // Now wait a human-scale duration, like 1/8 second.  In
        // practice we may be processing, since the sound is playing
        // asynchronously.

        synchronized (this) {
            try {
                wait(125); // wait 1/8 sec
            }
            catch (Exception e2) {
                say("huh?");
            }
        }
    } while (--countDown > 0);

}

/**
 * 'Sam' is a class that implements one method, playIt(), that simply
 * plays the .wav file clip it was instantiated with.  Just using an
 * inner class here for simplicity of demo.
 */
final class Sam {

    AudioInputStream ais;
    Clip             clip;

    /**
     * Constructor: prepare clip to be played. Do as much here as 
     * possible, to minimize the overhead of playing the clip, 
     * since I want to call the play() method 5-10 times a second.
     */
    Sam(String clipName) throws Exception {

        // Resource is in same directory as this source code.  
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL url = classLoader.getResource(clipName);
        ais = AudioSystem.getAudioInputStream(url);
        clip = AudioSystem.getClip();
        clip.open(ais);
    }

    /**
     * playIt(): Start the clip playing once, asynchronously, and exit. 
     */
    public void playIt() throws Exception {
        clip.setFramePosition(0);  // Must always rewind!
        clip.loop(0);
        clip.start();
    }
}

private static void say(String s) {
    System.out.println(s);
}
}