# sound zuverlässig wiedergeben



## SBehnen27 (23. Apr 2005)

hi.
ich würde gern für ein spiel kleine wav-files abspielen...

die sounds werden sich vorraussichtlich nicht überlappen (ausser, man klickt verdammt schnell)...

mein lösungsansatz sieht so aus:


```
public void playSound(String pfad){
        Sound Play = new Sound(pfad);
        Thread T = new Thread(Play);
        T.start();
    }
   /* diese innere Klasse spielt sounds ab.*/
    private class Sound implements Runnable{
        private String pfad;
        public Sound(String pfad){
            this.pfad = pfad;
        }
         public void run() {
            try{
                AudioClip ac = Applet.newAudioClip (new File (pfad).toURL()); //funktioniert auch in einer Application
                ac.play();
            }
            catch (Exception e){

            }
       }
    }
```

komisch nur, dass manchmal der ton verzögert kommt. manchmal kommt er gar nicht und manchmal ist er sofort da...
jemand ne ahnung, woran das liegt?

wies auch schon im code-kommentar steht: die klasse, die die sounds abspielt ist eine innere klasse, die in meinem spielfeld liegt. 
wenn ich nen ton abspielen will, starte ich die methode playSound und übergebe einen pfad für ne wav-file.

bin für jede hilfe dankbar


----------



## SBehnen27 (24. Apr 2005)

hm. kann ich aus den nicht vorhandenen antworten ableiten, dass das schon die optimale lösung ist?
ich hoffe doch nicht


----------



## Grizzly (25. Apr 2005)

Das dürfte zum Einen daran liegen, dass die Standard Sound Klassen von J2SE nicht so der Bringer sind. Für Sound lieber JMF verwenden. Zum Anderen muss Java die AudioClip erst einmal laden. In Deinem Fall jedes Mal, wenn er abgespielt werden soll. Du könntest mal versuchen, die Sounds vorher zu laden und dann nur noch abzuspielen.


----------



## EgonOlsen (26. Apr 2005)

Wieso machst du immer einen Thread pro Sound auf? Das tut wirklich nicht not, zumal du nie garantieren kannst, wann der eigentlich dran kommt. Das dürfte auch dein Problem erklären, wieso alles gleichzeitig und am Ende gespielt wird. Ferner ist wichtig zu wissen, das Java5 den Soundsupport "schön" verhunzt hat und es einen kleinen Workaround braucht, damit alles gut klappt. Anbei eine stark kastrierte Version meines Soundkrams für Paradroidz. Eine Instanz der Klasse repräsentiert dabei immer einen Sound. Die kannst du dann in einer getrennten Klasse irgendwie sinnvoll verwalten und einfach mit play() abspielen. Eine main-Methode zum schnellen Testen ist auch drin. Vielleicht hilft das...


```
import java.io.*;
import javax.sound.sampled.*;

public class StrippedSound {

   private static Mixer mixer;
   private byte[] data;
   private AudioFormat format;
   private DataLine.Info dataLineInfo;
   private boolean ok=false;
   private Clip currentLoopClip=null;
   private Clip lastClip=null;
   private boolean mute=false;

   static {
      Mixer.Info[] mixers=AudioSystem.getMixerInfo();
      for (int i=0; i<mixers.length; i++) {
         if ("Java Sound Audio Engine".equals(mixers[i].getName())) {
            mixer=AudioSystem.getMixer(mixers[i]);
         }
      }
   }

   public static void main(String[] args) {
     StrippedSound s1=new StrippedSound(new File("sound1.wav"));
     StrippedSound s2=new StrippedSound(new File("sound2.wav"));
     StrippedSound s3=new StrippedSound(new File("sound3.wav"));
     
     for (int i=0; i<50; i++) {
       double rnd=Math.random();
       if (rnd<0.3) {
         s1.play();
       }
       else {
         if (rnd < 0.6) {
           s2.play();
         }
         else {
           if (rnd < 1) {
             s3.play();
           }
         }
       }
       
       try {
         Thread.sleep(200);
       } catch(Exception e) {
         //egal
       }
     }
     
     while (s1.isRunning()||s2.isRunning()||s3.isRunning()) {
       // Warten, bis auch der letzte fertig ist...
       Thread.yield();
     }
     
     System.exit(0);
   }

   public StrippedSound(File sound) {
      try {
         System.out.println("Loading sound from file");
         AudioInputStream soundStream=AudioSystem.getAudioInputStream(sound);
         format=soundStream.getFormat();

         int len=(int) (format.getFrameSize()*soundStream.getFrameLength());
         data=new byte[len];
         int l=0;
         int lp=0;
         do {
            l=soundStream.read(data, lp, len);
            lp+=l;
         } while (l!=-1);

         dataLineInfo=new DataLine.Info(Clip.class, format);
         if (!AudioSystem.isLineSupported(dataLineInfo)) {
            System.out.println("Audio-Line not supported!");
         }
      } catch (Exception e) {
         System.out.println("Error loading sound: "+e);
      }
   }

   public void setMute(boolean is) {
      mute=is;
   }

   public boolean playedFine() {
      return ok;
   }

   public boolean isRunning() {
      return lastClip!=null&&lastClip.isRunning();
   }

   public void stop() {
      if (lastClip!=null&&lastClip.isRunning()) {
         lastClip.stop();
         lastClip=null;
      }
   }

   public void play() {
      if (mute) { return; }
      Clip soundClip=getClip();
      if (soundClip!=null) {
         soundClip.start();
      }
   }

   public void endLoop() {
      if (currentLoopClip!=null) {
         currentLoopClip.loop(0);
         currentLoopClip=null;
      }
   }

   public void loop() {
      if (mute) { return; }
      if (currentLoopClip==null) {
         currentLoopClip=getClip();
         if (currentLoopClip!=null) {
            currentLoopClip.loop(Clip.LOOP_CONTINUOUSLY);
         }
      }
   }

   private Clip getClip() {
      Clip soundClip;
      try {
         if (mixer!=null) {
            soundClip=(Clip) mixer.getLine(dataLineInfo);
         } else {
            soundClip=(Clip) AudioSystem.getLine(dataLineInfo);
         }
         soundClip.open(format, data, 0, data.length);
      } catch (LineUnavailableException e) {
         ok=false;
         return null;
      }
      ok=true;
      lastClip=soundClip;
      return soundClip;
   }
}
```


----------



## SBehnen27 (14. Mai 2005)

juhu.
Ich bin grade wieder auf mein Sound problem gestossen und habe dabei deine Antwort entdeckt...
Keine ahnung, warum ich die nicht früher gesehen habe.
Funktioniert auf jeden Fall prächtig *freu*

Danke dir.


----------



## snoop83 (1. Jun 2005)

genial..
Hab versucht mit mehreren Lösungen hier aus dem Forum sound abzuspielen .. mit Deiner Lösung funktioniert es nun endlich problemlos


----------



## EgonOlsen (2. Jun 2005)

Freut mich, dass die kleine Klasse hilfreich ist. Sound unter Java ist aber leider auch ein von SUN sehr stiefmütterlich behandeltes Thema und mit Java5 haben sie es endgültig verbockt (deshalb ist der static-Teil mit dem Mixer als Workaround drin).


----------



## pekadi (17. Jun 2006)

Ich hab die Klasse auch mal ausprobiert und bekomme diese Fehlermeldung:

Exception in thread "main" java.lang.IllegalArgumentException: Line unsupported: null
	at com.sun.media.sound.HeadspaceMixer.getLine(Unknown Source)
	at Test.getClip(Test.java:116)
	at Test.play(Test.java:89)
	at Test.main(Test.java:29)
Loading sound from file
Error loading sound: javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file


Kann mir jemand helfen??


----------



## Timmah (17. Jun 2006)

```
StrippedSound s1=new StrippedSound(new File("sound1.wav"));
StrippedSound s2=new StrippedSound(new File("sound2.wav"));
StrippedSound s3=new StrippedSound(new File("sound3.wav"));
```

Ich vermute mal, dass du diese Filenamen so gelassen hast, und diese bei dir gar nicht vorliegen? Ersetze sie durch welche, die es wirklich bei dir gibt.


----------



## EgonOlsen (17. Jun 2006)

Aus den API-Docs: "An UnsupportedAudioFileException is an exception indicating that an operation failed because a file did not contain valid data of a recognized file type and format."

Die Frage ist also: Was genau lädst du da für ein Format?


----------



## pekadi (17. Jun 2006)

Timmah hat gesagt.:
			
		

> ```
> StrippedSound s1=new StrippedSound(new File("sound1.wav"));
> StrippedSound s2=new StrippedSound(new File("sound2.wav"));
> StrippedSound s3=new StrippedSound(new File("sound3.wav"));
> ...



Nein, hab die Klasse schon angepasst.

Hier mein Code


```
import java.applet.*;
import java.io.File;
import java.net.*;
import javax.sound.sampled.*;


public class Test{
	
	private static Mixer mixer;
	private byte[] data;
	private AudioFormat format;
	private DataLine.Info dataLineInfo;
	private boolean ok=false;
	private Clip currentLoopClip=null;
	private Clip lastClip=null;
	private boolean mute=false;
	
	   static {
		      Mixer.Info[] mixers=AudioSystem.getMixerInfo();
		      for (int i=0; i<mixers.length; i++) {
		         if ("Java Sound Audio Engine".equals(mixers[i].getName())) {
		            mixer=AudioSystem.getMixer(mixers[i]);
		         }
		      }
		   } 
	   public static void main(String[] args) {
		     Test s1 = new Test(new File("Track1.wav")); 
		     
		s1.play();
		 
	       try {
	         Thread.sleep(200);
	       } catch(Exception e) {
	         //egal
	       }
	       while (s1.isRunning()) {
	           // Warten, bis auch der letzte fertig ist...
	           Thread.yield();
	         }
	         
	         System.exit(0);
	       }
	   
	   public Test(File sound) {
		      try {
		         System.out.println("Loading sound from file");
		         AudioInputStream soundStream=AudioSystem.getAudioInputStream(sound);
		         format=soundStream.getFormat();

		         int len=(int) (format.getFrameSize()*soundStream.getFrameLength());
		         data=new byte[len];
		         int l=0;
		         int lp=0;
		         do {
		            l=soundStream.read(data, lp, len);
		            lp+=l;
		         } while (l!=-1);

		         dataLineInfo=new DataLine.Info(Clip.class, format);
		         if (!AudioSystem.isLineSupported(dataLineInfo)) {
		            System.out.println("Audio-Line not supported!");
		         }
		      } catch (Exception e) {
		         System.out.println("Error loading sound: "+e);
		      }
		   }

		   public void setMute(boolean is) {
		      mute=is;
		   }

		   public boolean playedFine() {
		      return ok;
		   }

		   public boolean isRunning() {
		      return lastClip!=null&&lastClip.isRunning();
		   }

		   public void stop() {
		      if (lastClip!=null&&lastClip.isRunning()) {
		         lastClip.stop();
		         lastClip=null;
		      }
		   }

		   public void play() {
		      if (mute) { return; }
		      Clip soundClip=getClip();
		      if (soundClip!=null) {
		         soundClip.start();
		      }
		   }

		   public void endLoop() {
		      if (currentLoopClip!=null) {
		         currentLoopClip.loop(0);
		         currentLoopClip=null;
		      }
		   }

		   public void loop() {
		      if (mute) { return; }
		      if (currentLoopClip==null) {
		         currentLoopClip=getClip();
		         if (currentLoopClip!=null) {
		            currentLoopClip.loop(Clip.LOOP_CONTINUOUSLY);
		         }
		      }
		   }

		   private Clip getClip() {
		      Clip soundClip;
		      try {
		         if (mixer!=null) {
		            soundClip=(Clip) mixer.getLine(dataLineInfo);
		         } else {
		            soundClip=(Clip) AudioSystem.getLine(dataLineInfo);
		         }
		         soundClip.open(format, data, 0, data.length);
		      } catch (LineUnavailableException e) {
		         ok=false;
		         return null;
		      }
		      ok=true;
		      lastClip=soundClip;
		      return soundClip;
		   }
		}
```

Wie man oben sieht lade ich *.wav
Kann es sein, dass meine Wave Datei falsch erstellt ist? Hab das mit Nero gemacht.


----------



## pekadi (17. Jun 2006)

Hab den Fehler gefunden, anscheinend waren die Waves komprimiert. Kennt jemand ein gutes Tool um aus MP3 oder komprimierten Waves unkomprimierte zu erstellen?


----------



## foobar (17. Jun 2006)

Sounddecoder gibt es genügend. Hier gibt es einen Mp3decoder für Java: http://www.javazoom.net/index.shtml


----------



## EgonOlsen (18. Jun 2006)

Der ganze Soundkram (inkl. einer Version für LWJGL/OpenAL) findet sich übrigens hier drin: Paradroidz-Quellen


----------



## cybergen (11. Aug 2006)

Wie cool!!!   
Ich hab das vorher echt nicht hinbekommen... es kam kein Fehler, aber auch kein Ton...
Und Jetzt - einfach deine Klasse benutzt, und alles funzt einwandfrei!!!
VIELEN DANK!!!


Grüße
cybergen



----------------------------------------------------------
http://www.1st-cybergen.de


----------



## EgonOlsen (13. Aug 2006)

cybergen hat gesagt.:
			
		

> VIELEN DANK!!!


Keine Ursache...


----------

