Zum Inhalt springen

AudioClip erneut wiedergeben


Sporticus

Empfohlene Beiträge

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von 2K1.INC
Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...