Mit Java eigene Töne erzeugen ?!!?

GartenUmgraben

Erfahrenes Mitglied
Moin..

Ich wollte wissen ob jmd eine Möglichkeit kennt wie ich mit Java eigene Töne erzeugen kann, wie z.B. mit dem Tool Goldwave ( http://www.goldwave.com). Es geht nicht darum mit Java bereits vorhandeen Musik Dateien abzuspielen, sondern eigene zu erzeugen.

Sprich ich gebe verschiedene Werte wie z.B. Frequenz, Ampitude ec. vor und daraus wird dann der Ton erzeugt.

Gruß
Gärtner
 
Hallo,

hier mal ein Bsp.:

Java:
import javax.sound.sampled.Clip;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.AudioFormat;

public class ToneGeneratorExample {

        public byte[] getSinusTone(int frequency, AudioFormat af) {
            byte sample_size = (byte) (af.getSampleSizeInBits() / 8);
            byte[] data = new byte[(int) af.getSampleRate() * sample_size];
            double step_width = (2 * Math.PI) / af.getSampleRate();
            double x = 0;

            for (int i = 0; i < data.length; i += sample_size) {
                int sample_max_value = (int) Math.pow(2, af.getSampleSizeInBits()) / 2 - 1;
                int value = (int) (sample_max_value * Math.sin(frequency * x));
                for (int j = 0; j < sample_size; j++) {
                    byte sample_byte = (byte) ((value >> (8 * j)) & 0xff);
                    data[i + j] = sample_byte;
                }
                x += step_width;
            }
            return data;
        }

        public void play(int frequenzy) {
            AudioFormat af = new AudioFormat(44100, 16, 1, true, false);
            byte[] data = getSinusTone(frequenzy, af);
            try {
                Clip c = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));

                c.open(af, data, 0, data.length);
                c.start();
                c.loop(1000);
                while(c.isRunning()) {
                    try {
                        Thread.sleep(50);
                    } catch (Exception ex) {}
                }
            } catch (LineUnavailableException ex) {
                ex.printStackTrace();
            }
        }
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: ToneGeneratorExample <frequency>");
            System.exit(-1);
        }
        new ToneGeneratorExample().play(Integer.parseInt(args[0]));
    }
}

Zu beachten ist allerdings das je nachdem wie generisch man den Algorithmus zur Tonerzeugung implementieren will je komplizierter wird es und man sollte sich überlegen nicht doch zu einer externen API zu greifen. Der obere Weg umfasst zum Bsp nicht die Anzahl der Kanäle (mono/stereo), erzeugt nur Töne im Little Endian Format usw.

Gruß,
RedWing
 
Zuletzt bearbeitet:
Hallo, das Thema hier ist zwar schon ein paar Jahre alt, aber ich wollte doch mal anmerken: Bei dem Code da unten höre ich rein GAR nichts. Irgendeine Idee, wo ran das liegen könnte? Bei 440Hz sollte doch ein schönes A hörbar sein.
Ich würde mich sehr über eine Antwort freuen.
 
Ich habe den Code auch gerade getestet, auf anhieb höhre ich auch nichts. Wenn ich allerdings mit dem Debugger durchgehe, höre ich das A. Warscheinlich "stirbt" das Objekt zu schnell, da direkt danach das Program vorbei ist.

Hier eine leicht abgeänderte variante

Code:
public class ToneGenerator {
	
	/** die Tonleiter (C, D, E, F, G, A, H, C²*/
	private double frequencies[] = {261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25};
	
	 public byte[] getSinusTone(double frequency, AudioFormat af) {
         byte sample_size = (byte) (af.getSampleSizeInBits() / 8);
         byte[] data = new byte[(int) af.getSampleRate() * sample_size];
         double step_width = (2 * Math.PI) / af.getSampleRate();
         double x = 0;

         for (int i = 0; i < data.length; i += sample_size) {
             int sample_max_value = (int) Math.pow(2, af.getSampleSizeInBits()) / 2 - 1;
             int value = (int) (sample_max_value * Math.sin(frequency * x));
             for (int j = 0; j < sample_size; j++) {
                 byte sample_byte = (byte) ((value >> (8 * j)) & 0xff);
                 data[i + j] = sample_byte;
             }
             x += step_width;
         }
         return data;
     }

     public void play(double frequenzy) {
         AudioFormat af = new AudioFormat(44100, 16, 1, true, false);
         byte[] data = getSinusTone(frequenzy, af);
        
         try {
             Clip c = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));

             c.open(af, data, 0, data.length);
             c.start();
//             c.loop(1000);
             
//             while(c.isRunning()) {
//                 try {
//                     Thread.sleep(50);
//                 } catch (Exception ex) {}
//             }
             
         } catch (LineUnavailableException ex) {
             ex.printStackTrace();
         }
     }
     
     public void playGamut() {
    	for (double tone : this.frequencies) {
			play(tone);
			
	    	 try {
	 			Thread.sleep(500);
	 		} catch (InterruptedException e) {
	 			e.printStackTrace();
	 		}
		}
     }
     
     public static void main(String[] args) {
    	 ToneGenerator t = new ToneGenerator();
    	 t.playGamut();
	}
}
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück