Wav-Dateien wiederholt abspielen

RungetSvohu

Bekanntes Mitglied
Halllo,

es soll hier um mein Anliegen gehen, dass ich gestern bereits hier vortrug. Dort riet man mir jedoch, besser einen neuen Thread zu starten, da der alte schon als erledigt markiert war.

So möchte ich die Diskussion nun hierher verlagern.

Das dort beschriebene Problem tritt nur auf, wenn der Zeitpunkt, zu dem der Sound wiederholt abgespielt werden soll, ungefähr mit der Länge des Sounds übereinstimmt. Wie es zu dem Problem kommt, ist also klar. Nur wie lässt es sich lösen?

Danke!
 
Halllo,

es soll hier um mein Anliegen gehen, dass ich gestern bereits hier vortrug. Dort riet man mir jedoch, besser einen neuen Thread zu starten, da der alte schon als erledigt markiert war.

So möchte ich die Diskussion nun hierher verlagern.

Das dort beschriebene Problem tritt nur auf, wenn der Zeitpunkt, zu dem der Sound wiederholt abgespielt werden soll, ungefähr mit der Länge des Sounds übereinstimmt. Wie es zu dem Problem kommt, ist also klar. Nur wie lässt es sich lösen?

Danke!
Gute Idee... dein Problem scheint doch etwas tiefgreifender zu sein. Ich hab' mal folgendes versucht...
Java:
import static javax.sound.sampled.AudioSystem.*;
import static javax.sound.sampled.AudioFormat.Encoding.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

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

public class NewClip {
	private static final int FRAMESIZE = 4;

	private final SourceDataLine sdl;
	private final byte[] buffer;
	private int bytePos;
	private Thread runner;

	public NewClip(String soundfile) throws IOException {
		try {
			AudioInputStream ais = getAudioInputStream(new File(soundfile).getAbsoluteFile());
			AudioFormat af = ais.getFormat();
			if(!PCM_SIGNED.equals(af.getEncoding()) && !PCM_UNSIGNED.equals(af.getEncoding())) {
				af = new AudioFormat(PCM_SIGNED,
						af.getSampleRate(),
						af.getSampleSizeInBits() * 2,
						af.getChannels(),
						af.getChannels() * (af.getSampleSizeInBits() + 7) / 8,
						af.getSampleRate(),
						af.isBigEndian());
				ais = getAudioInputStream(af, ais);
			}
			int frameSize = af.getFrameSize();
			byte[] b = new byte[frameSize];
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			int r = 0;
			while((r = ais.read(b)) >= 0) {
				bos.write(b, 0, r);
			}
			sdl = getSourceDataLine(af);
			sdl.open(af);
			buffer = bos.toByteArray();
		} catch(UnsupportedAudioFileException | LineUnavailableException e) {
			throw new IOException(e);
		}
	}

	public synchronized void start() {
		if(sdl.isOpen() && runner == null) {
			runner = new Thread("NewClip") {
				@Override
				public void run() {
					sdl.start();
					while(!isInterrupted()) {
						try {
							if(bytePos + FRAMESIZE > buffer.length) {
								int l = buffer.length % FRAMESIZE;
								if(l != 0) {
									sdl.write(buffer, bytePos, l);
								}
								sdl.drain();
								bytePos = 0;
								synchronized(this) {
									wait();
								}
							}
							sdl.write(buffer, bytePos, FRAMESIZE);
							bytePos += FRAMESIZE;
						} catch(InterruptedException e) {
							interrupt();
						}
					}
					sdl.flush();
					sdl.stop();
				}
			};
			bytePos = 0;
			runner.start();
		}
	}

	public synchronized void stop() {
		if(runner != null) {
			runner.interrupt();
			try {
				runner.join();
			} catch(InterruptedException e) {
				// nothing
			}
			runner = null;
		}
	}

	public synchronized boolean isRunning() {
		return runner != null;
	}

	public synchronized void setFramePosition(int pos) {
		bytePos = pos * FRAMESIZE;
		if(runner != null) {
			synchronized(runner) {
				runner.notify();
			}
		}
	}

	public int getFramePosition() {
		return bytePos / FRAMESIZE;
	}

	public synchronized void close() {
		stop();
		sdl.close();
	}

	public static void main(String[] args) throws Exception {
		final NewClip chimes = new NewClip("chimes.wav");
		JFrame nervTest = new JFrame("nervTest");
		ActionListener al = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!chimes.isRunning()) {
					chimes.start();
				}
				chimes.setFramePosition(0);
			}
		};
		JButton nervButton = new JButton("auf dauer nervender Sound");
		nervButton.addActionListener(al);
		nervTest.add(nervButton);
		nervTest.pack();
		nervTest.setVisible(true);
	}
}
...und hab' so das Gefühl, als ob hier das gleiche Phänomen wie beim Clip auftritt, obwohl das eigentlich durch anhalten statt stoppen beseitigt sein sollte. Entweder hab' ich noch einen Denkfehler oder es liegt im nativen Bereich des DirectAudioDevices. Was auch noch möglich aber eher unwahrscheinlich ist, der EDT könnte durch eine hohe Anzahl an Clicks überfordert sein. Ist dann wohl die Stelle, an welcher man in einem MouseListener einen ClickCount > 1 bekäme.
 
Nachtrag: Wenn man Zeile 68 ([c]sdl.drain()[/c]) auskommentiert oder löscht, halten sich diese "Lags" noch ein wenig mehr in Grenzen. Ich denke besser geht's dann nicht.
 

Neue Themen


Zurück
Oben