Come posso riprodurre l'audio in Java?


Risposte:


133

Ho scritto il seguente codice che funziona bene. Ma penso che funzioni solo con il .wavformato.

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

7
Per evitare che Clip venga arrestato in modo casuale, è necessario un LineListener. Date un'occhiata: stackoverflow.com/questions/577724/trouble-playing-wav-in-java/...
Yanchenko

3
+1 per una soluzione che utilizza l'API pubblica. Tuttavia, la creazione di un nuovo thread non è necessaria (ridondante)?
Jataro,

4
Grazie .. È ridondante? L'ho trasformato in un nuovo thread in modo da poter riprodurre nuovamente il suono prima della fine della prima clip.
pek

4
So che clip.start () genera un nuovo thread, quindi sono abbastanza sicuro che non sia necessario.
Jataro,

44
1) Non Threadè necessario. 2) Per un buon esempio di utilizzo Clip, consultare le informazioni su JavaSound. pagina . 3) Se un metodo richiede un URL(o File) dargli un dang URL(o File) piuttosto che accettare un Stringche rappresenta uno. (Solo un '"ape nel mio cofano" personale.) 4) e.printStackTrace();fornisce più informazioni con meno battute di System.err.println(e.getMessage());.
Andrew Thompson,

18

Un cattivo esempio:

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

13
java.sun.com/products/jdk/faq/faq-sun-packages.html Esistono alternative API pubbliche all'utilizzo di sun.audio.
McDowell,

4
@GregHurlman Non è il pacchetto sun. * Creato per non essere utilizzato da noi sviluppatori?
Tom Brito,

36
Questo esempio viene da un articolo JavaWorld del 1997. Non aggiornato, NON si devono usare i pacchetti sun. *.
sproketboy,

3
hai mai bisogno di chiudere "in"?
rogerdpack, il

6
+1 per non usare il sole. * Pacchetti. Hanno strani bug come non gestire file> 1 MB e non essere in grado di riprodurre una clip se la precedente non è ancora finita, ecc.
rogerdpack,

10

Non volevo avere così tante righe di codice solo per riprodurre un suono dannatamente semplice. Questo può funzionare se hai il pacchetto JavaFX (già incluso nel mio 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();
}

Avviso: è necessario inizializzare JavaFX . Un modo rapido per farlo è chiamare il costruttore di JFXPanel () una volta nella tua app:

static{
    JFXPanel fxPanel = new JFXPanel();
}

8

Per riprodurre l'audio in Java, è possibile fare riferimento al seguente codice.

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

7

Per qualsiasi motivo, la risposta migliore di wchargin mi stava dando un errore null pointer quando stavo chiamando this.getClass (). GetResourceAsStream ().

Ciò che ha funzionato per me è stato il seguente:

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

E vorrei riprodurre il suono con:

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

sounds / effects / sheep1.wav si trovava nella directory di base del mio progetto in Eclipse (quindi non all'interno della cartella src).


ciao Anrew, il tuo codice ha funzionato per me, ma ho notato che ci vuole un po 'di tempo in più in esecuzione ... circa 1,5 sec.

getResourceAsStream()restituirà nullse la risorsa non viene trovata o genera l'eccezione se lo nameè null- non è un errore della risposta principale se il percorso indicato non è valido
user85421

3

Qualche tempo fa ho creato un framework di gioco per lavorare su Android e Desktop, la parte desktop che gestisce il suono può forse essere utilizzata come ispirazione per ciò di cui hai bisogno.

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

Ecco il codice di riferimento.

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

}

Questo codice potrebbe causare errori nel stream.reset();portare a Resetting to invalid mark. Cosa proponi di fare per risolvere questo problema?
Dima

magari ricreare lo stream, vedi stackoverflow.com/questions/18573767/…
hamilton.lima

1
In realtà l'ho risolto usando raw.mark(raw.available()+1)dopo l'inizializzazione rawe poi nel ciclo while, quindi usando raw.reset()invece di stream.reset(). Il mio problema ora è che quando si tratta di ripristinare, c'è un divario tra i giochi. Voglio ottenere un ciclo continuo come te Clip. Non sto usando Clipperché manipolare i controlli come MASTER_GAIN ha un notevole ritardo di ~ 500ms. Probabilmente questa dovrebbe essere una domanda che mi chiederò in seguito.
driima,

Non un do { ... } while?
Andreas,

2

Esiste un'alternativa all'importazione dei file audio che funziona sia nelle applet che nelle applicazioni: converti i file audio in file .java e semplicemente usali nel tuo codice.

Ho sviluppato uno strumento che rende questo processo molto più semplice. Semplifica parecchio l'API Java Sound.

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


Ho usato il tuo sistema per creare una classe da un file wav, tuttavia, When do my_wave.play (); non riproduce l'audio .. Esiste un sistema audio che devo inizializzare o qualcosa del genere? ..
Nathan F.

sarebbe davvero bello se funzionasse davvero. Quando si esegue play (), get Audio Line ha esito negativo (eccezione "java.lang.IllegalArgumentException: nessuna interfaccia di corrispondenza riga SourceDataLine che supporta il formato PCM_UNSIGNED 44100,0 Hz, 16 bit, stereo, 4 byte / frame, little-endian è supportato." Non è supportato. torta). Triste.
phil294,

2

Sono sorpreso che nessuno abbia suggerito di usare Applet. Usa Applet . Dovrai fornire il file audio del segnale acustico come wavfile, ma funziona. Ho provato questo su 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

2
Appletè obsoleto a partire da Java 9.
Fre_d

0

Questo thread è piuttosto vecchio ma ho determinato un'opzione che potrebbe rivelarsi utile.

Invece di utilizzare la AudioStreamlibreria Java è possibile utilizzare un programma esterno come Windows Media Player o VLC ed eseguirlo con un comando console tramite Java.

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

Ciò creerà anche un processo separato che può essere controllato dal programma.

p.destroy();

Ovviamente l'esecuzione richiederà più tempo rispetto all'utilizzo di una libreria interna, ma potrebbero esserci programmi che possono avviarsi più velocemente e possibilmente senza una GUI dato determinati comandi della console.

Se il tempo non è essenziale, questo è utile.


4
Anche se penso che questa sia una soluzione oggettivamente negativa (in termini di affidabilità, efficienza e altre metriche simili), è almeno una soluzione interessante che altrimenti non avrei mai pensato!
Max von Hippel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.