Sounds laden ... nur wie ?

Aber Ja doch… Du verwendest einen eigenen Play-Thread in welchem du den Stream selbst in eine SourceDataLine streamst. Einen solchen Thread kannst du starten wann du willst, befüllen wann und wie du willst und stoppen wann du willst. Z.B. wie hier

http://forum.byte-welt.net/showpost.php?p=23551&postcount=10

So ungefähr?

...
JFrame f;
...
Thread t = new Thread(new Runnable(){
@Override
public void run(){
while(f.isVisible()){
if(soundabspielen){
clip.start();
}
}
}
}
);
...
public void tueWas(boolean geklickt) throws Exeption{ // ist in eigenem Thread
if(geklickt){
t.start()
Thread.sleep(Dauer des Sounds in ms);
t.stop();
}

NEEEEIIIINNN!!!einseinself :lol:
Aber fast. Spar dir das “Thread.sleep()” und sorge in der “.run()”-Methode dafür, dass sich der Thread von selbst abschaltet, wenn der Sound zuende ist.

Und wenn ich gleichzeitig mit dem Sound Einen Text und eine sprech-Animation einbauen möchte wo muss das dann hin?
Bsp. CodeBlock:

drawString = true;
repaint();
tueAnimation(); // Enthält auch Thread.sleep()
drawString = false;
repaint();

Dann solltest du dieses drawString-Boolean im SoundThread unterbringen, es von diesem setzen und löschen lassen und entweder das repaint() in der run-Methode ausführen (Signalmethode) oder falls das repaint eh’ zyklisch erfolgt drawString per get-Methode in der repaint-Methode abfragen.

jetzt spielt er den Sound ab, und schreibt den Text, doch dann hängt sich das Programm auf, woran kann das liegen ? außerdem ist es mir nicht gelungen das Thread.sleep() aus der methode zu verbannen.

s.satz1= true;
s.repaint();
s.currentsoundindex = 1;
s.abspielen = true;
try {
Thread.sleep(seq[s.currentsoundindex].getMicrosecondLength());
} catch (InterruptedException e) {
e.printStackTrace();
}
s.abspielen = false;
s.satz1 = false;
s.repaint();

Also alles was ich jetzt noch tun kann, ist dir ein kleines KSKB zu zeigen, welches du als Grundlage nehmen solltest…

import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SoundDemo extends JPanel {
	private static final long serialVersionUID = 1L;

	final Player p;

	public SoundDemo() {
		p = new Player(this);
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		String out = (p.isPlaying())? "playing" : "not playing";
		g.drawString(out, 0, 20);
	}

	public static void main(String[] args) {
		final JFrame f = new JFrame();
		final JButton b = new JButton("play");
		final SoundDemo s = new SoundDemo();
		f.setLayout(new BorderLayout());
		f.add(b, BorderLayout.SOUTH);
		f.add(s, BorderLayout.CENTER);
		b.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!s.p.isPlaying()) {
					new Thread(s.p).start();
				}
			}
		});
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.pack();
		f.setVisible(true);
	}
}

class Player implements Runnable {
	private final JPanel p;
	private boolean playing;

	Player(JPanel p) {
		this.p = p;
	}

	boolean isPlaying() {
		return playing;
	}

	@Override
	public void run() {
		try {
			AudioInputStream in = ensurePCM(AudioSystem.getAudioInputStream(new File("addicted.wav")));
			SourceDataLine out = AudioSystem.getSourceDataLine(in.getFormat());
			byte[] buffer = new byte[out.getBufferSize()];
			out.open();
			out.start();
			p.repaint();
			int r;
			playing = true;
			while(playing) {
				try {
					r = in.read(buffer);
					if(r < 0) {
						playing = false;
						break;
					}
					out.write(buffer, 0, r);
				} catch(IOException e) {
					playing = false;
				}
			}
			out.stop();
			out.drain();
			out.close();
			p.repaint();
		} catch(UnsupportedAudioFileException | IOException | LineUnavailableException e) {
			return;
		}
	}

	private static 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;
	}
}```

Das Beispiel funktioniert nicht, wenn man auf den Knopf drückt passiert nichts

@Spacerat : Tststs…leere catch-Blöcke…
Als erstes könnte man mal in alle “catch”-Blöcke ein
e.printStackTrace();
reinschreiben, und schauen, ob DANN was ausgegeben wird.

:o
Obwohl… der Catch-Block ist ja nicht leer, da steht immerhin ein return drin. Allerdings fällt mir noch was anderes auf, deswegen hier noch mal die veränderte Run-Methode:

	public void run() {
		SourceDataLine out = null;
		try {
			AudioInputStream in = ensurePCM(AudioSystem.getAudioInputStream(new File("addicted.wav")));
			out = AudioSystem.getSourceDataLine(in.getFormat());
			byte[] buffer = new byte[out.getBufferSize()];
			out.open();
			out.start();
			p.repaint();
			int r;
			playing = true;
			while(playing) {
				try {
					r = in.read(buffer);
					if(r < 0) {
						playing = false;
					}
					out.write(buffer, 0, r);
				} catch(IOException e) {
					playing = false;
				}
			}
		} catch(UnsupportedAudioFileException | IOException | LineUnavailableException e) {
			e.printStackTrace();
		} finally {
			if(out != null) {
				out.stop();
				out.drain();
				out.close();
			}
			p.repaint();
		}
	}```

Ich bekomme eine NullPointerException:
Exception in thread „Thread-6“ java.lang.NullPointerException
at Java.Soc.Socius$1.run(Socius.java:148)
at java.lang.Thread.run(Unknown Source)

bei
out[currentsoundindex].stop();
:confused:

Kann mir nicht helfen, aber dieser Fehler sieht mir sehr danach aus, als hättest du den Code meiner Run-Methode schlicht mit C+P in deinen Code eingefügt und soweit verändert, bis keine Compiler-Fehler mehr auftauchen. Das Resultat ist dann ein solches wie bei dir.
Als erstes solltest du mal versuchen mein KSKB mit der geänderten Run-Metode nachzuvollziehen, bei mir kommt da zumindest höchstens mal eine FileNotFoundException wenn die Datei nicht gefunden wurde oder eine UnsupportedAudioFileException, wenn ich eine MP3 abspielen will, aber den Codec nicht installiert habe.
Ansonsten kann ich für Anfänger in der Spiele-Entwicklung erst mal nur Quaxlis Tutorial empfehlen.

die filenotfoundException hab ich schon gelöst und das ganze hat auch funktioniert, bis ich die sourceDataLine in einen Array gepackt hab.
Die run-methode hab ich üprigens auch verstanden bis auf:

		while(playing) {
		try {
		r = in[currentsoundindex].read(buffer);
		if(r < 0) {
		playing = false;
		}
		out[currentsoundindex].write(buffer, 0, r);
		} catch(IOException e) {
		playing = false;
		}
		}

Dann ist ja alles klar…
Du musst dich nur noch davon lösen, alle Sounds ohne Mixing in einem Thread ausführen zu wollen, mit anderen Worten, du must pro Sounddatei einen kompletten PlayerThread erstellen, in welchem dann natürlich keine Arrays vorkommen.

Hier nochmal ein weiteres Beispiel aus 'nem anderen Thread.
http://forum.byte-welt.net/threads/9677-JLayer-player-übergibt-0?p=59233&viewfull=1#post59233

Wenn ich Zeit hab’ schreib’ ich evtl. mal 'nen Blog über die Sound-API.

nur so aus Intresse, warum geht das mit Arrays in einem einzigen Thread nicht ?

Ganz banal… weil Arrays nicht Thread-Save sind. Aber es geht natürlich schon, nur ist der Aufwand höher. Wie sollte man sich sonst 'ne ultimative SoundRenderEngine basteln können?

Und ich hab jetst die Runnable in eine externe Class gepackt in der ich alle Runnables sammeln will, aber jetzt steht weder was auf dem Bildschirm, noch ist etwas zu hören.


Runnable r1 = new Runnable(){

public void run() {
	try {
		try {
			out1.open();
		} catch (LineUnavailableException e1) {
			e1.printStackTrace();
		}
		out1.start();
    byte[] buffer = new byte[out1.getBufferSize()];
	s.satz1 = true;
	s.repaint();
	int r;
	playing = true;
	s.currentindex = 1;
	while(playing) {
    s.currentindex++;
	try {
	r = in1.read(buffer);
	if(r < 0) {
	playing = false;
	}
	out1.write(buffer, 0, r);
	} catch(IOException e) {
	playing = false;
	}
	try {
		s.t.sleep((long) (clip1.getMicrosecondLength()/1000000.0)/s.currentstring.length());
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	s.repaint();
	}
	} finally {
	if(out1 != null) {
		out1.stop();
		out1.drain();
		out1.close();
	}
	s.satz1 = false;
	s.repaint();
	}
	}
};


if(sr.isPlaying()) {
    new Thread(sr.r1).start();
}

Ich hab kein Plan, was du da machst. Schon wieder dieses “Thread.sleep()” und danach scheinst du die Soundausgabe einfach abzubrechen… Hier nochmal ein weiteres Beispiel mit 2 Sounds, die man unabhängig starten und stoppen kann sowie einem FPS-Counter, der den GameLoop emuliert. Wie du siehst läuft da alles parallel (auf Multicore-CPUs sogar wirklich).

import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SoundDemo extends JPanel {
	private static final long serialVersionUID = 1L;

	final Player[] p;
	final Thread gameLoop;
	long frame, time;
	double fps, frameTime;

	public SoundDemo(String... soundFiles) {
		p = new Player[soundFiles.length];
		for(int n = 0; n < p.length; n++) {
			p[n] = new Player(this, soundFiles[n]);
		}
		gameLoop = new Thread() {
			@Override
			public void run() {
				while(!isInterrupted()) {
					calculate();
					repaint();
				}
			}

			private void calculate() {
				// whatever has to be calced goes here;
				long t = System.nanoTime();
				long delta = t - time;
				if (delta >= 250000000) {
					fps = frame * 1000000000.0 / delta;
					frameTime = 1000000.0 / fps;
					time = t;
					frame = 0;
				}
			}
		};
		gameLoop.start();
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		frame++;
		int x = 15;
		for(int n = 0; n < p.length; n++) {
			g.drawString(p[n].getSoundFile() + " " + ((p[n].isPlaying())? "playing" : "not playing"), 0, x);
			x += 15;
		}
		String ff = String.format("@%1.3ffps", fps);
		String ft = String.format("frameTime: %1.3fus", frameTime);
		g.drawString(ff, 0, x);
		g.drawString(ft, 0, x + 15);
	}

	public static void main(String[] args) {
		final JFrame f = new JFrame();
		final SoundDemo s = new SoundDemo("addicted.mp3", "naked.mp3");
		final JPanel buttons = new JPanel();
		buttons.setLayout(new GridLayout(1, s.p.length * 2));
		for(int n = 0; n < s.p.length; n++) {
			final int index = n;
			JButton b = new JButton(s.p[n].getSoundFile() + " |>");
			b.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if(!s.p[index].isPlaying()) {
						new Thread(s.p[index]).start();
					}
				}
			});
			buttons.add(b);
			b = new JButton(s.p[n].getSoundFile() + " []");
			b.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					s.p[index].stop();
				}
			});
			buttons.add(b);
		}
		f.setLayout(new BorderLayout());
		f.add(buttons, BorderLayout.SOUTH);
		f.add(s, BorderLayout.CENTER);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.pack();
		f.setVisible(true);
	}
}

class Player implements Runnable {
	private final JPanel p;
	private final String soundFile;
	private boolean playing;

	Player(JPanel p, String soundFile) {
		if(soundFile == null) {
			throw new NullPointerException();
		}
		this.soundFile = soundFile;
		this.p = p;
	}

	boolean isPlaying() {
		return playing;
	}

	String getSoundFile() {
		return soundFile;
	}

	void stop() {
		playing = false;
	}

	@Override
	public void run() {
		SourceDataLine out = null;
		try {
			AudioInputStream in = ensurePCM(AudioSystem.getAudioInputStream(new File(soundFile)));
			out = AudioSystem.getSourceDataLine(in.getFormat());
			byte[] buffer = new byte[out.getBufferSize()];
			out.open();
			out.start();
			p.repaint();
			int r;
			playing = true;
			while(playing) {
				try {
					r = in.read(buffer);
					if(r < 0) {
						playing = false;
						break;
					}
					out.write(buffer, 0, r);
				} catch(IOException e) {
					playing = false;
				}
			}
		} catch(UnsupportedAudioFileException | IOException | LineUnavailableException e) {
			e.printStackTrace();
		} finally {
			if(out != null) {
				out.stop();
				out.drain();
				out.close();
			}
			p.repaint();
		}
	}

	private static 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;
	}
}```

Wie ich gerade gelernt habe, gibt es auch thread-save Varianten der Collections, zu finden unter java.util.concurrent.

[QUOTE=Crian]Wie ich gerade gelernt habe, gibt es auch thread-save Varianten der Collections, zu finden unter java.util.concurrent.[/QUOTE]Erstens OT, zweitens Collections sind nicht die klassischen Arrays, also die mit den Klammern ([]). :wink:
Ansonsten stimmt das… z.B. ist „java.util.Vector“ die Thread-Safe-Variante von „java.util.ArrayList“.