Как приложение Java может воспроизводить аудиоклип? - PullRequest
1 голос
/ 17 июня 2011

Ниже приведена ссылка на наиболее вероятное объяснение, которое я видел, но у меня все еще есть вопросы.

Как воспроизвести звук на 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. Работает ли это в приложении, в отличие от апплета?
  2. Метод Main.class.getResourceAsStream (), кажется, требует import com.sun.tools.apt.Main; , но я не могу найти документацию для этого, и я не знаю, что он делает. Например, является ли "/ path / to / sounds /" абсолютным или относительным, а если последнее, относительно где?

Я провел много часов, пытаясь воспроизвести простой звуковой эффект. Невероятно, насколько это сложно. Я надеюсь, что приведенный выше код можно заставить работать. Спасибо за любую помощь.

Chap

Ответы [ 3 ]

1 голос
/ 17 июня 2011
  1. Это должно работать в приложении.
  2. Эта строка кода, скорее всего, ссылается на класс, в котором находится метод. Так что этот метод изначально был в классе Main, если вы поместили метод в классFooBar, вы должны изменить его на FooBar.class.getResourceAsStream ().
  3. Это относительный путь.Он будет искать ресурс за пределами каждого пакета.Пример: предположим, что класс, на котором выполняется этот фрагмент кода, находится в C: \ Users \ Jeffrey \ bin \ foo \ bar \ SoundPlayer.class, а класс находится в пакете foo.bar.Это означает, что ClassLoader будет искать ресурсы в папке C: \ Users \ Jeffrey \ bin \.(В вашем случае, он будет искать ресурс по адресу C: \ Users \ Jeffrey \ bin \ path \ to \ sounds \ + url)

Я всегда загружал звуки так:

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

но ваш метод также должен работать.

1 голос
/ 17 июня 2011

Работает ли это в приложении, в отличие от апплета?

Работает либо в.

Метод Main.class.getResourceAsStream (), по-видимому, требует import com.sun.tools.apt.Main;

Откуда у вас эта идея? Я привел множество убедительных примеров и никогда не слышал о том классе, который вам не следует использовать.

.. но я не могу найти документацию для этого, ..

Нет, классы com.sun не только недокументированы, но и могут измениться в следующей микроверсии.

.. и я не знаю, что он делает. Например, является ли "/ path / to / sounds /" абсолютным или относительным, а если последнее, относительно где?

Относительно корня пути к классам.

.. Невероятно, насколько это сложно.

Обработка мультимедиа в целом - сложная задача.


Кстати - я не сильно впечатлен кодом в связанном потоке. Оболочка Thread не нужна, как упоминалось в нескольких комментариях, даже для одновременного воспроизведения нескольких экземпляров Clip.

Вместо этого посмотрите этот код , который я (писал &) лично рекомендую.

0 голосов
/ 20 июня 2011

Несмотря на то, что я много рисовал из кода @ Эндрю, мне пришлось кое-где подправить. Ниже приведена демонстрационная версия моего решения, за исключением образца 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);
}
}
...