Ich möchte in der Lage sein, Audiodateien in meinem Programm abzuspielen. Wo soll ich suchen?
Ich möchte in der Lage sein, Audiodateien in meinem Programm abzuspielen. Wo soll ich suchen?
Antworten:
Ich habe den folgenden Code geschrieben, der gut funktioniert. Aber ich denke, es funktioniert nur mit .wav
Format.
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();
}
Thread
ist unnötig. 2) Ein gutes Beispiel für die Verwendung Clip
finden Sie in den JavaSound-Informationen. Seite . 3) Wenn eine Methode ein URL
(oder File
) erfordert, geben Sie ihr einen Dang URL
(oder File
), anstatt einen zu akzeptieren String
, der einen darstellt. (Nur eine persönliche 'Biene in meiner Haube'.) 4) e.printStackTrace();
liefert mehr Informationen mit weniger Eingabe als System.err.println(e.getMessage());
.
Ein schlechtes Beispiel:
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);
Ich wollte nicht so viele Codezeilen haben, nur um einen einfachen verdammten Sound zu spielen. Dies kann funktionieren, wenn Sie das JavaFX-Paket haben (das bereits in meinem JDK 8 enthalten ist).
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();
}
Hinweis: Sie müssen JavaFX initialisieren . Eine schnelle Möglichkeit, dies zu tun, besteht darin, den Konstruktor von JFXPanel () einmal in Ihrer App aufzurufen:
static{
JFXPanel fxPanel = new JFXPanel();
}
Informationen zum Abspielen von Sound in Java finden Sie im folgenden Code.
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();
}
}
Aus irgendeinem Grund gab mir die Top-Antwort von wchargin einen Nullzeigerfehler, als ich this.getClass (). GetResourceAsStream () aufrief.
Was für mich funktioniert hat, war Folgendes:
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();
}
Und ich würde den Sound spielen mit:
playSound("sounds/effects/sheep1.wav");
Sounds / Effects / Schaf1.wav befand sich im Basisverzeichnis meines Projekts in Eclipse (also nicht im Ordner src).
getResourceAsStream()
kehrt , null
wenn die Ressource nicht gefunden wird, oder die Ausnahme auslösen , wenn name
ist null
- kein Fehler der Top - Antwort , wenn der angegebene Pfad ist nicht gültig
Ich habe vor einiger Zeit ein Spiel-Framework für Android und Desktop erstellt. Der Desktop-Teil, der den Sound verarbeitet, kann möglicherweise als Inspiration für Ihre Anforderungen verwendet werden.
Hier ist der Code als Referenz.
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();
Führen zu fehlerhaft sein Resetting to invalid mark
. Was schlagen Sie vor, um dies zu beheben?
raw.mark(raw.available()+1)
nach der Initialisierung raw
und dann in der while-Schleife und dann raw.reset()
anstelle von verwendet habe stream.reset()
. Mein Problem ist jetzt, dass es beim Zurücksetzen eine Lücke zwischen den Spielen gibt. Ich möchte eine Endlosschleife erreichen, wie Sie sie erhalten Clip
. Ich benutze es nicht, Clip
weil das Manipulieren von Steuerelementen wie MASTER_GAIN eine merkliche Verzögerung von ~ 500 ms hat. Dies sollte wahrscheinlich eine eigene Frage sein, die ich später stellen werde.
do { ... } while
?
Es gibt eine Alternative zum Importieren der Audiodateien, die sowohl in Applets als auch in Anwendungen funktioniert: Konvertieren Sie die Audiodateien in Java-Dateien und verwenden Sie sie einfach in Ihrem Code.
Ich habe ein Tool entwickelt, das diesen Prozess erheblich vereinfacht. Dies vereinfacht die Java Sound API erheblich.
Ich bin überrascht, dass niemand Applet vorgeschlagen hat. Verwenden Sie Applet
. Sie müssen die Signalton-Audiodatei als wav
Datei angeben, aber es funktioniert. Ich habe das unter Ubuntu versucht:
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
ist ab Java 9 veraltet.
Dieser Thread ist ziemlich alt, aber ich habe eine Option festgelegt, die sich als nützlich erweisen könnte.
Anstatt die Java- AudioStream
Bibliothek zu verwenden, können Sie ein externes Programm wie Windows Media Player oder VLC verwenden und es mit einem Konsolenbefehl über Java ausführen.
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();
}
Dadurch wird auch ein separater Prozess erstellt, der vom Programm gesteuert werden kann.
p.destroy();
Die Ausführung dauert natürlich länger als die Verwendung einer internen Bibliothek, aber es kann Programme geben, die bei bestimmten Konsolenbefehlen schneller und möglicherweise ohne GUI gestartet werden können.
Wenn die Zeit nicht entscheidend ist, ist dies nützlich.