Sporticus Geschrieben 12. Juni 2011 Geschrieben 12. Juni 2011 Hi Community, ich experementiere momentan mit der Wiedergabe von Sounds via Java (javax.sound.sampled*) rum und bräuchte dabei mal eure Hilfe. Das erzeugen eines solchen Sounds an sich ist nicht weiter schwer, allerdings hab ich es noch nicht geschafft, eine Sounddatei (.wav oder .mp3) erneut wiederzugeben. Hier mal mein aktueller Code. Die Methode, in der das AudioClip Objekt erzeugt wird: private AudioClip loadMP3AudioClip(File file) { try { AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); AudioFormat baseFormat = audioInputStream.getFormat(); AudioFormat decodedFormat = new AudioFormat( AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false ); DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, decodedFormat); SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo); AudioClip clip = new AudioClip(file.getName(), audioInputStream, decodedFormat, sourceDataLine); return clip; } catch (UnsupportedAudioFileException e) { } catch (IOException e) { } catch (LineUnavailableException e) { } return null; } Die Klasse AudioClip, die beim laden einer Sounddatei erzeugt wird: import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; public class AudioClip implements Runnable { private final String name; private final AudioInputStream baseAudioInputStream; private final AudioFormat audioFormat; private final SourceDataLine sourceDataLine; private boolean paused = false; private boolean stoped = false; private boolean muted = false; private int count; /** * @param name * @param audioInputStream * @param audioFormat * @param sourceDataLine * @param dataLineInfo */ public AudioClip(String name, AudioInputStream audioInputStream, AudioFormat audioFormat, SourceDataLine sourceDataLine) { this.name = name; this.baseAudioInputStream = audioInputStream; this.audioFormat = audioFormat; this.sourceDataLine = sourceDataLine; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { try { sourceDataLine.open(audioFormat); if(count > 0) { for (int i = 0; i < count; i++) { play(); reset(); } } else { while(true) { play(); reset(); } } } catch (LineUnavailableException e) { log.error("", e); } finally { sourceDataLine.drain(); sourceDataLine.stop(); sourceDataLine.close(); IOUtils.closeQuietly(baseAudioInputStream); } } private void play() { try { AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(audioFormat, this.baseAudioInputStream); byte[] tempBuffer = new byte[10000]; sourceDataLine.start(); int cnt; while((cnt = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) { // --- // Stop if(stoped) { return; } // --- // Pause while(paused) { if(sourceDataLine.isRunning()) { sourceDataLine.stop(); } try { Thread.sleep(100); } catch (InterruptedException e) { log.error("", e); } } if(!sourceDataLine.isRunning()) { sourceDataLine.start(); } // --- // Running if(cnt > 0 && !muted) { sourceDataLine.write(tempBuffer, 0, cnt); } } } catch (IOException e) { log.error("", e); } } /** * */ public void mute() { if(muted) { muted = false; } else { muted = true; } } /** * */ public void pause() { if(paused) { paused = false; } else { paused = true; } } /** * */ public void stop() { stoped = true; } /** * */ public void reset() { // TODO } /** * @param count */ public void setPlayCount(int count) { this.count = count; } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { return name; } /** * @return */ public AudioClip copy() { return new AudioClip(name, baseAudioInputStream, audioFormat, sourceDataLine); } } In der Methode Reset (TODO): Hier soll der Stream zurückgesetzt werden, um ihn erneut wiederzugeben Allerdings bekomm ich bei dem Methodenaufruf von der Methode von AudioInputStream.reset() eine Exception: java.io.IOException: mark/reset not supported at java.io.InputStream.reset(InputStream.java:334) at javax.sound.sampled.AudioInputStream.reset(AudioInputStream.java:410) at de.fh.game.engine.sound.impl.AudioClip.reset(AudioClip.java:174) at de.fh.game.engine.sound.impl.AudioClip.run(AudioClip.java:71) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) Meine Frage: Wie kann ich eine Sounddatei erneut wiedergeben, ohne neu in das Programm zu laden? Ich hoffe, dass mir der ein oder andere hoffentlich weiterhelfen kann. Danke Zitieren
2K1.INC Geschrieben 15. Juni 2011 Geschrieben 15. Juni 2011 (bearbeitet) hey, du hast ja private final AudioInputStream baseAudioInputStream; diese Klasse besitzt eine reset methode versuchs mir der. EDIT: zu spät gelesen das dus damit schon versucht hast EDIT2: also ich habs so verstanden das reset dahin geht wo du zuletzt es mit der mark methode aufgezeichnet hast, die nutzt du aber nicht somit bekommst ja ne exception weil er ja dahin spirngen will was nicht da ist. versuchs mal am afang mit mark und dann mit der reset. Bearbeitet 15. Juni 2011 von 2K1.INC Zitieren
Sporticus Geschrieben 15. Juni 2011 Autor Geschrieben 15. Juni 2011 hi, ja das mit der mark(int)-Methode hab ich auch schon probiert. An die muss man ja ein int Parameter übergeben, an welcher Stelle man den Stream makieren will. Soweit ich das verstanden hab. Demzufolge müsste ich also schreiben: baseAudioInputStream.mark(0); Allerdings funktioniert das auch nicht (hab ich auch schon ausprobiert), aber wie man aus der Exception lesen kann, kann man entnehmen, dass mark/reset-Funktion nicht unterstützt werden. Die Frage ist jetzt, wie kann ich das aktivieren oder eben einen anderen Weg nehmen, um an die Lösung zu kommen. Zitieren
Sporticus Geschrieben 16. Juni 2011 Autor Geschrieben 16. Juni 2011 Hi, ich bin mitlerweile selber auf die Lösung gekommen, nachdem ich mir nochmal die API von den ganzen Sound Klassen angesehen habe. Dabei bin ich auf das Interface Clip gestoßen. Und genau das war die Lösung. Hier nun die Lösung als Code: private AudioClip2 loadAudioClipWAV(File file) { try { AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); DataLine.Info info = new DataLine.Info(Clip.class, audioInputStream.getFormat()); Clip c = (Clip) AudioSystem.getLine(info); c.open(audioInputStream); c.addLineListener(new ClipLineListener()); AudioClip2 clip = new AudioClip2(file.getName(), c); clips.put(clip.getName(), clip); return clip; } catch (UnsupportedAudioFileException e) { log.error("", e); } catch (IOException e) { log.error("", e); } catch (LineUnavailableException e) { log.error("", e); } return null; } private final class ClipLineListener implements LineListener { /* (non-Javadoc) * @see javax.sound.sampled.LineListener#update(javax.sound.sampled.LineEvent) */ public void update(LineEvent event) { if(LineEvent.Type.STOP == event.getType()) { event.getLine().close(); } } } zum starten der Wiedergabe: clip.loop(count); ...oder... clip.start(); Vielen Dank Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.