Sounderzeugung mit Java

wakoz

Erfahrenes Mitglied
Hallo

Ich möchte mittels Java einen Sound erzeugen, ich habe ein HowToDo gefunden was mich sehr weit gebracht hat.

Nun habe ich ein Problem, wenn ich mit dem was ich gefunden habe einen Ton erzeugt habe habe ich immer ein Knacken vor und nach dem Ton. Das kann ich aber so nicht gebrauchen!

Da ich über Threads nicht nur einen einzelnen Ton erzeuge, sondern mehrere Töne hintereinander ist das Knacken ein Störfaktor.

Dies ist "mein" Code
Code:
package sound.model;

import java.util.ArrayList;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

public class SoundGenerator {
	public SoundGenerator(){
		System.out.println("Erzeugt");
	}

	/**
	 * Generates a tone.
	 * 
	 * @param herz
	 *            Base frequency (neglecting harmonic) of the tone in cycles per
	 *            second
	 * @param milliseconds
	 *            The number of milliseconds to play the tone.
	 * @param volume
	 *            Volume, form 0 (mute) to 100 (max).
	 * @param addHarmonic
	 *            Whether to add an harmonic, one octave up.
	 */
	public void generateOneTone(Double herz, int milliseconds, int volume,
			boolean addHarmonic) throws LineUnavailableException {

		float frequency = 44100;
		byte[] buf;
		AudioFormat af;
		if (addHarmonic) {
			buf = new byte[2];
			af = new AudioFormat(frequency, 8, 2, true, false);
		} else {
			buf = new byte[1];
			af = new AudioFormat(frequency, 8, 1, true, false);
		}
		SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
		sdl.open(af);
		sdl.start();
		for (int i = 0; i < milliseconds * frequency / 1000; i++) {
			double angle = i / (frequency / herz) * 2.0 * Math.PI;
			buf[0] = (byte) (Math.sin(angle) * volume);

			if (addHarmonic) {
				double angle2 = (i) / (frequency / herz) * 2.0 * Math.PI;
				buf[1] = (byte) (Math.sin(2 * angle2) * volume * 0.6);
				sdl.write(buf, 0, 2);
			} else {
				sdl.write(buf, 0, 1);
			}
		}
		sdl.drain();
		sdl.stop();
		sdl.close();
	}
	
	/**
	 * Generates a tone.
	 * 
	 * @param herz
	 *            Base frequency (neglecting harmonic) of the tone in cycles per
	 *            second
	 * @param milliseconds
	 *            The number of milliseconds to play the tone.
	 * @param volume
	 *            Volume, form 0 (mute) to 100 (max).
	 * @param addHarmonic
	 *            Whether to add an harmonic, one octave up.
	 */
	public void generateTones(ArrayList<Double> soundValues, int milliseconds, int volume,
			boolean addHarmonic) throws LineUnavailableException {

		for (Double herz : soundValues) {
			float frequency = 44100;
			byte[] buf;
			AudioFormat af;
			if (addHarmonic) {
				buf = new byte[2];
				af = new AudioFormat(frequency, 8, 2, true, false);
			} else {
				buf = new byte[1];
				af = new AudioFormat(frequency, 8, 1, true, false);
			}
			SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
			sdl.open(af);
			sdl.start();
			for (int i = 0; i < milliseconds * frequency / 1000; i++) {
				double angle = i / (frequency / herz) * 2.0 * Math.PI;
				buf[0] = (byte) (Math.sin(angle) * volume);
				
				if (addHarmonic) {
					double angle2 = (i) / (frequency / herz) * 2.0 * Math.PI;
					buf[1] = (byte) (Math.sin(2 * angle2) * volume * 0.6);
					sdl.write(buf, 0, 2);
				} else {
					sdl.write(buf, 0, 1);
				}
			}
			sdl.drain();
			sdl.stop();
			sdl.close();
			
		}
	}
	
}

ziel des ganzen ist mit allen Double Werten aus einer Tabelle zusammenhängende Töne zu erzeugen.
Das klappt durch Zwei Threads die abwechselnd einen Ton erzeugen ganz gut, nur ist zwischen den tönen immer das knacken was stört :(

Vielleicht könnte es auch alle töne in eine Sound File zuschreiben und diese gebunden auszugeben. Weiß aber nicht wie ich die Double werte umwandle und dann in eine Sound File schreiben kann, alles was ich bislang gefunden hab arbeitet sonst mit richtigen tönen. Bin aber nicht wirklich in der Lage das auf das zu Mappen was ich benötige.
 
Also das Knacken kommt vermutlich von Frequenz-Sprüngen. Evtl. versuchst Du wirklich die Daten in eine WAV-Datei zu exportieren, dann kannst Du die Spuren mit einem Sound-Editor analysieren und siehst evtl. die Fehler.
 
Danke für deine Antwort, wenn das so ist dann kann ich es gleich aufgeben weil die Frequenz Sprünge kommen aus den Urdaten wenn ich diese glätten möchte...

naja dann werde ich wohl ne Sound api nutzen und die Double werte Mappen :(
 
Zurück