Hallo zusammen,
die Literatur und das Internet konnten mir bisher nicht weiterhelfen, weil es doch wohl ein sehr spezielles Thema ist. Ich brauche Unterstützung von jemandem, der sich im Sound-Sampling auskennt. Was mache ich falsch? Die Kiste gibt zwar keinen Fehler aus, aber hören tut man auch nix. Ich bin mir hinsichtlich der zahlreichen Parameter, die es beim Sound-Sampling gibt, aber auch noch nicht so 100-%-ig sicher - mangels Literatur ;-). Ich habe mal ein möglichst knappes Programm geschrieben, das natürlich auch nicht funktioniert, und möchte gerne wissen, was falsch ist. Bitte um Hilfe!
die Literatur und das Internet konnten mir bisher nicht weiterhelfen, weil es doch wohl ein sehr spezielles Thema ist. Ich brauche Unterstützung von jemandem, der sich im Sound-Sampling auskennt. Was mache ich falsch? Die Kiste gibt zwar keinen Fehler aus, aber hören tut man auch nix. Ich bin mir hinsichtlich der zahlreichen Parameter, die es beim Sound-Sampling gibt, aber auch noch nicht so 100-%-ig sicher - mangels Literatur ;-). Ich habe mal ein möglichst knappes Programm geschrieben, das natürlich auch nicht funktioniert, und möchte gerne wissen, was falsch ist. Bitte um Hilfe!
Java:
import java.io.*;
import javax.sound.sampled.*;
public class Sinuston {
// Meine Parameter:
float frequenz = 558.15f; // Frequenz des Sinustons in Hz (ungefähr ein "cis")
float mySampleRate = 44100f; // Frequenz des Samplings in Hz
int mySampleSizeInBits = 16; // Auflösung der Abtastung; ein Sample umfasst 16 Bit = 2 Byte.
int myChannels = 2; // Ich mags Stereo
int myFrameSizeInByte = (int)(mySampleSizeInBits / 2 * myChannels);
int amplitude = 30000; // Entspricht der Lautstärke; eine "Verstärkung" des y-Wertes der Sinus-
// Funktion
float myFrameRate = mySampleRate; // Java: "The number of frames played or recorded per second"
boolean myBigEndian = false; // Die Bedeutung des "Big-Endian" oder "Little-Endian" in diesem Kontext
// ist mir noch unklar!!
// Liefert die Sampling-Daten eines Sinustons in Form eines Byte-Streams zurück:
public ByteArrayOutputStream SinusDaten() {
ByteArrayOutputStream oByteReihe = new ByteArrayOutputStream();
/* Errechnet zu jedem Zeitpunkt eines Samples (Bruchteil einer Sekunde) den Sinuswert. Mathematisch
betrachtet: Sinus = Winkelfunktion; Eine Sinuskurve ist vollständig abgelaufen, wenn quasi der Einheits-
kreis (r = 1) einmal umrundet ist, beginnend bei Bogenmaß = 0, endendend bei Bogenmaß = Kreißumfang =
2 x r x Pi = 2 x 1 x Pi = 2 x Pi. Der Einheitskreis muss 558,15 Mal pro Sekunde umrundet werden (= Frequenz:
558,15 Hz). 1 Umrundung dauert 1/558,15 sec. Frage: Welcher Sinuswert besteht bei z. B. einer 3/44100 sec.
(3. Abtastpunkt)?
*/
double BMBruchteil = (double)(frequenz / mySampleRate); // BMBruchteil = Bogenmaßbruchteil pro Sample (0,0127)
// Umkehrschluss: 1 Sinusschwingung hat 0,0127 x 558,15 Hz
// = ca. 7 Abtastpunkte (Samples).
double Kreisumfang = (float)(Math.PI * 2); // entspr. 360° = 1 abgeschlossene Sinuskurve; siehe Mathe-Buch ;-).
double Bogenmass = 0;
double Sinus;
for (int i = 0; i <= mySampleRate; i = i++) {
Sinus = (Math.sin(Bogenmass)) * amplitude;
// Schreibe an den ByteStream:
oByteReihe.write((byte)Sinus);
// Schreibe den 2. Byte:
oByteReihe.write((byte)Sinus >>> 8);
// Für nächsten Abtastpunkt:
Bogenmass = Bogenmass + Kreisumfang * BMBruchteil;
}
return oByteReihe;
}
public void SinusTonAbspielen() {
// Definiere ein Audio-Format:
AudioFormat aif = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, // empfohlen in einem Buch
mySampleRate, // 44100
mySampleSizeInBits, // 16 Bit
myChannels, // 2 = Stereo
myFrameSizeInByte, // 4, resultierend aus SampleSizeInBits und Channels
myFrameRate, // 44100
myBigEndian); // false; empfohlen in einem Buch
// Für den Sinuston einen Audio-Inputstream:
ByteArrayOutputStream bos = SinusDaten();
InputStream is = new ByteArrayInputStream(bos.toByteArray());
AudioInputStream ais = new AudioInputStream(is, aif, bos.size() / aif.getFrameSize());
// Jetzt brauche ich eine Line, ...
DataLine.Info myDataLineInfo = new DataLine.Info(Clip.class, aif);
// ... die ich auf einen Clip caste:
Clip myClip = null;
try {
myClip = (Clip)AudioSystem.getLine(myDataLineInfo);
} catch (LineUnavailableException e) {
System.out.println("Line mag nicht auf Clip!");
System.exit(0);
}
// Jetzt wrid's ernst: Der Clip soll abgespielt werden:
try {
myClip.open(ais);
} catch (LineUnavailableException e) {
System.out.println("Der Clip mag nicht (LineUnavailableException)!");
} catch (IOException e) {
System.out.println("Der Clip mag nicht (IOException)");
}
}
public static void main(String[] args) {
Sinuston st = new Sinuston();
st.SinusTonAbspielen();
}
}