# Sound einbinden funktioniert nicht



## _java_freak_ (21. Aug 2012)

Hallo Forum,
ich programmiere schon seit kurzem ein Spiel doch leider will die Sound einbindung nicht so ganz funktionieren. Ich habe auf vielen Seiten geschaut aber geklappt hat es nie. Also wenn ihr eine Möglichkeit kennt die besser einfacher oder sonst was ist sagt es einfach ahnung auch über Seiten mit Tutorials würde ich mich sehr freuen. In meinem Code sind sehr wahrscheinlich mehr Imports als notwendig da ich von den Seiten immer wieder Imports kopiert habe und diese süäter nicht gelöscht habe. Nun zu meinem Code.
Zuerst die Klasse mit dem Menü Optionen gehen noch nicht:

```
import java.awt.Graphics;

import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton.*;
import javax.*;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import Rennen.*;

public class AutoMenu extends JPanel
{
    JButton start;
    JButton optionen;
    JButton beenden;
    int Lautstärke=100;

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        start=new JButton("Start");
        optionen=new JButton("Optionen");
        beenden=new JButton("Beenden");
        
        beenden.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                System.exit(0);
            }
        });
        
        start.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                Rennen rennen=new Rennen(Lautstärke);
            }
        });
        
        add(start);
        add(optionen);
        add(beenden);
    }


    public static void main(String[] args) {

        JFrame frame = new JFrame("Menu");
        frame.add(new AutoMenu());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(100, 150);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }
}
```

Und nun zur Problem Klasse dort wird die Musik abgespielt:

```
import java.awt.Graphics;

import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton.*;
import javax.*;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.sampled.*;
import java.io.*;
import javax.swing.*;
import sun.audio.*;
import java.net.*;
import java.util.*;
import java.lang.*;
import java.applet.*;

class Rennen extends JPanel
{
      JFrame frame;

      public Rennen(int Lautstärke)
      {
             JFrame frame = new JFrame("Rennen");
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.setSize(500, 500);
             frame.setLocationRelativeTo(null);
             frame.setVisible(true);

             sound();
      }

      public void sound()
      {
             try
             {
                 URL url = this.getClass().getClassLoader().getResource("C:/Users/uli J/Documents/ajava/2d/Rennen/Fahren.wav");
                 AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
                 Clip clip = AudioSystem.getClip();
                 clip.open(audioIn);
                 clip.start();
             }
             catch (UnsupportedAudioFileException e)
             {
                 e.printStackTrace();
             }
             catch (IOException e)
             {
                 e.printStackTrace();
             }
             catch (LineUnavailableException e)
             {
                 e.printStackTrace();
             }
      }
}
```
Danke für jede Hilfe!


----------



## Spacerat (22. Aug 2012)

1. Der Dateiname der Wav-Datei ist keine Jar-Relative URL, da musst du entweder AudioSystem.getAudioInputStream(File) verwenden oder die URL mittels File.toURI().toURL() instanzieren.
2. Die Wav-Datei könnte theoretisch ein nicht Widergabefähiges Encoding aufweisen. In diesem Fall benötigst du noch:

```
private final AudioInputStream ensurePCM(AudioInputStream source)
	{
		AudioFormat af = source.getFormat();
		Encoding enc = af.getEncoding();
		if(!PCM_SIGNED.equals(enc) && !PCM_UNSIGNED.equals(enc)) {
			int ssb = af.getSampleSizeInBits();
			int c = af.getChannels();
			if(ssb < 8) {
				ssb = 8;
			}
			int minFs = c * ssb / 8;
			int fs = af.getFrameSize();
			if(fs < minFs) {
				fs = minFs;
			}
			af = new AudioFormat(
					AudioFormat.Encoding.PCM_SIGNED,
					af.getSampleRate(),
					ssb * 2,
					af.getChannels(),
					fs * 2,
					af.getSampleRate(),
					af.isBigEndian()
				);
			source = AudioSystem.getAudioInputStream(af, source);
		}
		return source;
	}
```


----------



## Marco13 (22. Aug 2012)

Als ich den Code eben gesehen habe sind mir die Augen geplatzt und blutige Fontänen aus den Augenhöhlen gespritzt  Du willst wahrscheinlich NICHT bei jedem Neuzeichnen neue Buttons erstellen und dem Panel hinzufügen. Schau mal Trail: Creating a GUI With JFC/Swing (The Java™ Tutorials) einigermaßen systematisch durch, und ggf. auch sowas wie Malen in Swing Teil 1: der grundlegende Mechanismus ? Byte-Welt Wiki . In der paint-Methode (bzw. in paintComponent) sollte NUR gezeichnet werden.

Zum eigentlichen Problem: Probier' es mal isoliert

```
package snippet;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Snippet
{
    public static void main(String[] args)
    {
        try
        {
            AudioInputStream audioIn = AudioSystem.getAudioInputStream(new File("./chimes.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            clip.start();
            Thread.sleep(1000);
        }
        catch (UnsupportedAudioFileException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (LineUnavailableException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}
```
Mit der "chimes.wav" aus C:\windows\media. Wenn das nichts abspielt, .... ist irgendwas im Argen. Dann mal statt "chimes.wav" deine Datei verwenden. Wenn das nichts abspielt: Welches Format hat die WAV?

EDIT: Spacerat mal wieder ....


----------



## _java_freak_ (22. Aug 2012)

So in der abgesonderten Datei von Marco13 klappt das Abspielen der Datei wenn ich es aber in meiner Klasse mache klappt nichts mehr.
Hier noch einmal der neue Code:

```
import java.awt.Graphics;

import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton.*;
import javax.*;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.sampled.*;
import java.io.*;
import javax.swing.*;
import sun.audio.*;
import java.net.*;
import java.util.*;
import java.lang.*;
import java.applet.*;



import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;




class Rennen extends JPanel
{
      JFrame frame;

      public Rennen(int Lautstärke)
      {
             JFrame frame = new JFrame("Rennen");
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.setSize(500, 500);
             frame.setLocationRelativeTo(null);
             frame.setVisible(true);

             sound();
      }

      public void sound()
      {
             try
             {
                 AudioInputStream audioIn = AudioSystem.getAudioInputStream(new File("C:/Users/uli J/Documents/ajava/2d/Rennen/Fahren.wav"));
                 Clip clip = AudioSystem.getClip();
                 clip.open(audioIn);
                 clip.start();
                 Thread.sleep(1000);
             }
        catch (UnsupportedAudioFileException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (LineUnavailableException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
      }
}
```
Was mache ich nun falsch?
Das Problem mit dem neu laden der Buttons habe ich danke der Hilfe von Marco13 auch gelöst. Die links habe ich mir zwar noch nicht angeschaut aber das werde ich im Verlauf des Tages wahrscheinlich noch tuen.


----------



## Spacerat (22. Aug 2012)

Also entweder dass funktioniert, oder es gibt 'nen Stacktrace (also 'ne Fehlermeldung). Dieser wird für weitere Hilfen benötigt.


----------



## _java_freak_ (22. Aug 2012)

Da kommt keine Fehlermeldung aber der Ton wird trotzdem nicht abgespielt.


----------



## Spacerat (22. Aug 2012)

In diesem Fall... :bahnhof:
Setz mal 'ne Zeile mit 'ner Konsolenausgabe in die "sound()"-Methode. Nur um festzustellen, das sie überhaupt ausgeführt wird. Ansonsten... weisst du was Debugging ist?


----------



## _java_freak_ (22. Aug 2012)

Na toll ich habe jetzt die Konsolenausgaben gemacht sie kommen nicht das komische wenn ich das ganze aber mit der Funktion

```
public static void main(String[] args)
      {
             new Rennen(100);
      }
```
starte die ich direkt in diese klasse geschrieben habe funktioniert es sonst hab ich nichts geändert. Mit dem Debugging funktioniert das auch nicht ganz da ich sobald man einen der Knöpfe drücken muss um weiter zu kommen kommt der debugger nicht mehr und der Ton wird auch nicht abgespielt. Und nebenbei noch eine Frage kann man irgendwo die Lautstärke einstellen?


----------



## Spacerat (22. Aug 2012)

Das letzte ist einfach beantwortet: Ja, man kann. Dazu musst du dir vom Clip die Volume- oder Master-Gain-Contol beschaffen. Aber gerade beim Thema Lautstärke ist die Java-Sound-API nicht immer sehr intuitiv, denn sie arbeitet mit den Werten, welche die Soundhardware verlangt, wobei es sich weit verbreitet um DeziBell- (also logarythmische) statt um prozentuale bzw. lineare Werte handelt. Nach "clip.open()" also:
[JAVA=21]FloatControl vol = null;
if(!clip.isControlSupported(FloatControl.Type.VOLUME)) {
  if(clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
    vol = clip.getControl(FloatControl.Type.MASTER_GAIN);
  }
} else {
  vol = clip.getControl(FloatControl.Type.VOLUME);
}
if(vol != null) {
  float minimum = dBToLinear(vol.getMinimum());
  float range = dBToLinear(vol.getMaximum()) - minimum;
  vol.setValue(linearToDB(Lautstärke / 100.0f * range + minimum));
}[/code]
Dazu benötigst du noch die beiden Utility-Methoden dBToLinear und linearToDB, welche du beliebig (statisch oder nicht) aber erreichbar irgendwo im Code plazieren kannst:

```
private float linearToDB(float f)
{
  float f1 = (float) ((Math.log((f != 0.0) ? f : 1.0E-14) / Math.log(10.0)) * 20.0);
  return f1;
}

private float dBToLinear(float f)
{
  float f1 = (float) Math.pow(10.0, f / 20.0);
  return f1;
}
```
Das erste ist zwar nicht weniger leicht zu beantworten, aber 'ne Lösung dafür...  hmm. Versuch' mal festzustellen, warum "Rennen" nicht aufgerufen wird.


----------



## _java_freak_ (22. Aug 2012)

Es geht jetzt ich hattee die Klasse rennen vorher in einem anderen ordner und habe es dann mit import eingebunden aber das hat anscheinend nicht funktioniert. Noch mal zur Lautstärke ich muss da bei

```
if(vol != null) {
  float minimum = dBToLinear(vol.getMinimum());
  float range = dBToLinear(vol.getMaximum()) - minimum;
  vol.setValue(linearToDB(Lautstärke / 100.0f * range + minimum));
}
```
die Variable Lautstärke ändern und dann wird es lauter wenn der wert höher ist oder? Und ist das dann in prozent oder einfach zahlen von 0 bis irgendwas? Danke für die ganzen Antworten!!! :applaus:


----------



## Spacerat (22. Aug 2012)

nur Zahlen von 0 bis 100 bitte. Wenn du die Einstellungen feiner haben willst, musst du bei "/ 100.0" 'ne höhere Zahl einsetzen. Das ist der obere Grenzwert.


----------



## _java_freak_ (22. Aug 2012)

Das mit der Lautstärke geht irgendwie nicht ich bekomm da 2 fehlermeldungen incompitable types in zeile 29 ,34 ich habe dazu das programm von marco13 genommen da dies übersichtlicher und kürzer ist.


```
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.FloatControl.*;
import javax.sound.sampled.Control.*;
import javax.sound.sampled.*;

public class Snippet
{
    public static void main(String[] args)
    {
        try
        {
            AudioInputStream audioIn = AudioSystem.getAudioInputStream(new File("C:/Users/uli J/Documents/ajava/2d/Fahren.wav"));
            Clip clip = AudioSystem.getClip();
            clip.open(audioIn);
            
            FloatControl vol = null;

            if(!clip.isControlSupported(FloatControl.Type.VOLUME))
            {
              if(clip.isControlSupported(FloatControl.Type.MASTER_GAIN))
              {
                vol = clip.getControl(FloatControl.Type.MASTER_GAIN);
              }
            }
            else
            {
              vol = clip.getControl(FloatControl.Type.VOLUME);
            }
            if(vol != null)
            {
              float minimum = dBToLinear(vol.getMinimum());
              float range = dBToLinear(vol.getMaximum()) - minimum;
              vol.setValue(linearToDB(100 / 100.0f * range + minimum));
            }
            
            clip.start();
            

            
            Thread.sleep(5000);
        }
        catch (UnsupportedAudioFileException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (LineUnavailableException e)
        {
            e.printStackTrace();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    public static float linearToDB(float f)
    {
       float f1 = (float) ((Math.log((f != 0.0) ? f : 1.0E-14) / Math.log(10.0)) * 20.0);
       return f1;
    }

    public static float dBToLinear(float f)
    {
       float f1 = (float) Math.pow(10.0, f / 20.0);
       return f1;
    }
    
    
}
```
Was mache ich falsch oder muss ich noch ein Import einbinden?


----------



## Spacerat (22. Aug 2012)

Da fehlen die Casts...
[JAVA= 29]                vol = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);[/code]
und
[JAVA= 34]                vol = (FloatControl) clip.getControl(FloatControl.Type.VOLUME;[/code]


----------



## _java_freak_ (22. Aug 2012)

Funktioniert jetzt Danke!!!


----------

