Come può un'applicazione Java riprodurre una clip audio?


Quanto segue è un link alla spiegazione più probabile che ho visto, ma ho ancora domande.

Come posso riprodurre il suono in Java?

Citerò il codice qui:

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. Funziona in un'applicazione, al contrario di un'applet?
  2. Il metodo Principale.classe.getResourceAsStream () sembra richiedere import com.sole.strumenti.apt.Main; ma non riesco a trovare la documentazione per questo, e non so cosa faccia. Ad esempio, è "/path/to/ sounds / " assoluto, o relativo, e se quest'ultimo, relativo a dove?

Ho passato molte ore a cercare di riprodurre un semplice effetto sonoro. E ' incredibile quanto sia difficile. Spero che il codice di cui sopra possa essere fatto funzionare. Grazie per l'aiuto.

Cap

Author: Community, 2011-06-17

3 answers

  1. Che dovrebbe funzionare in un'applicazione.
  2. Quella riga di codice fa probabilmente riferimento alla classe in cui si trova il metodo. Quindi quel metodo era originariamente nella classe Main, se metti il metodo nella classe FooBar, dovresti cambiarlo in FooBar.classe.getResourceAsStream ().
  3. È un percorso relativo. Cercherà la risorsa al di fuori di ogni pacchetto. Esempio: diciamo che la classe che sta eseguendo questo pezzo di codice si trova a C:\Users\Jeffrey\bin\foo\bar\SoundPlayer.classe e il la classe è nel pacchetto foo.bar. Ciò significa che il ClassLoader cercherà le risorse all'interno del C:\Users\Jeffrey\bin \ cartella. (Nel tuo caso, cercherà la risorsa a C:\Users\Jeffrey\bin\path\to\sounds \ + url)

Ho sempre caricato suoni come questo:

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

Ma anche il tuo metodo dovrebbe funzionare.

 1
Author: Jeffrey, 2011-06-17 17:15:32

Funziona in un'applicazione, al contrario di un'applet?

Funziona in entrambi.

Il metodo Principale.classe.getResourceAsStream () sembra richiedere import com.sole.strumenti.apt.Principale;

Dove ti è venuta quest'idea? Ho fatto molti esempi sonori e non ho mai sentito parlare di quella classe che non dovresti usare.

..ma non riesco a trovare documentazione per questo,..

No, le classi com.sun non sono solo prive di documenti, ma potrebbe cambiare nella prossima micro-versione.

..e non capisco cosa faccia. Ad esempio, "/ path / to / sounds / " è assoluto, o relativo, e se quest'ultimo, relativo a dove?

È relativo alla radice del percorso di classe.

Unbelievable È incredibile quanto sia difficile.

La gestione dei media in generale è complicata.


BTW - Non sono molto impressionato dal codice sul thread collegato. Il wrapper Thread è inutile, come menzionato in molti dei commenti, anche per la riproduzione simultanea di più istanze Clip.

Invece vedi questo codice che (scritto e) raccomando personalmente.

 1
Author: Andrew Thompson, 2017-05-23 11:55:38

Anche se ho attinto pesantemente dal codice di @Andrew, ho dovuto fare alcune modifiche qua e là. Quanto segue è una demo della mia soluzione, completa tranne che per un esempio .file 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);
}
}
 0
Author: Chap, 2011-06-19 22:00:10