diff --git a/Envelope.java b/Envelope.java
new file mode 100644
index 0000000..19aad01
--- /dev/null
+++ b/Envelope.java
@@ -0,0 +1,81 @@
+/**
+ * Implementation der ADSR-Huellkurve
+ * Fuer die Facharbeit vom 16.03.2017
+ * Objekte dieser Klasse fuehren die Berechnung
+ * der Funktionswerte der Huellkurve aus.
+ * 2017, Soeren Richter
+ * soeren@dreieck-project.de
+ * Version 0.1.5
+ * Code vollstaendig selbst geschrieben, fuer Hintergruende und
+ * Referenzen siehe Abschnitt 3.6 der Facharbeit.
+ * @author Soeren Richter
+ * @version 0.1.5
+ */
+
+public class Envelope
+{
+ // konstante ADSR-Attribute der Huellkurve:
+ private final double attack;
+ private final double decay;
+ private final double sustain;
+ private final double release;
+
+ // veraenderbare Hold-Zeit/Tonlaenge:
+ private double length;
+
+ /**
+ * Konstruktor der Klasse Envelope.
+ * @param pAttack Attack-Zeit der Huellkurve
+ * @param pDecay Decay-Zeit der Huellkurve
+ * @param pSustain Sustain-Amplitude der Huellkurve
+ * @param pRelease Release-Zeit der Huellkurve
+ */
+ public Envelope(double pAttack, double pDecay, double pSustain, double pRelease)
+ {
+ attack = pAttack;
+ decay = pDecay;
+ sustain = pSustain;
+ release = pRelease;
+ length = 1;
+ }
+
+ /**
+ * Rueckgabe des Huellkurven-Funktionswertes zum Zeitpunkt time
+ * @param time Zeitpunkt in s
+ * @return Huellkurven-Funktionswert
+ */
+ public double getAmplitude(double time)
+ {
+ double amp = 0;
+ if (time <= attack) {
+ amp = time/attack;
+ } else if (time <= attack+decay && time > attack) {
+ amp = (-1 + sustain) / decay * time + (1 - sustain)
+ / decay * (attack + decay) + sustain;
+ } else if (time <= length && time > attack+decay) {
+ amp = sustain;
+ } else if (time > length) {
+ amp = (-sustain) / release * time + sustain
+ / release * length + sustain;
+ }
+ return amp;
+ }
+
+ /**
+ * Festlegen der Hold-/Tonlaenge
+ * @param pLength Hold-/Tonlaenge in s
+ */
+ public void setLength(double pLength)
+ {
+ length = pLength;
+ }
+
+ /**
+ * Rueckgabe der vollstaendigen Huellkurvenlaenge inklusive Release-Zeit
+ * @return vollstaendige Laenge der Huellkurve
+ */
+ public double getFullLength()
+ {
+ return length+release;
+ }
+}
diff --git a/Oscillator.java b/Oscillator.java
new file mode 100644
index 0000000..b6c4d0d
--- /dev/null
+++ b/Oscillator.java
@@ -0,0 +1,128 @@
+/**
+ * Implementation der Fourier-Reihen
+ * Fuer die Facharbeit vom 16.03.2017
+ * Objekte dieser Klasse fuehren die Berechnung der Funktionswerte
+ * der Fourier-Reihe ihrer entsprechnden Wellenform und Parameter aus.
+ * 2017, Soeren Richter
+ * soeren@dreieck-project.de
+ * Version 0.1.5
+ * Code vollstaendig selbst geschrieben. Fuer Referenzen und mathematische
+ * Grundlage siehe Kapitel 3 der Facharbeit.
+ * @author Soeren Richter
+ * @version 0.1.5
+ */
+
+public class Oscillator
+{
+ // Wellenform; "sine", "saw", "square" oder "triangle":
+ private final String waveform;
+
+ // Grenzfrequenz der berechnung der Fourier-Reihen-Summen
+ private final int cutoff;
+
+ /**
+ * Konstruktor der Klasse Oscillator.
+ * @param pWaveform Wellenform ("sine", "saw", "square" oder "triangle")
+ * @param pCutoff Grenzfrequenz der berechnung der Fourier-Reihen-Summen
+ */
+ public Oscillator(String pWaveform, int pCutoff)
+ {
+ waveform = pWaveform;
+ cutoff = pCutoff;
+ }
+
+ /**
+ * Berechnung des Funktionswertes einer Sinus-Funktion (Sine) der Frequenz frequency zum Zeitpunkt timeSample
+ * @param frequency Frequenz in Hz
+ * @param timeSample Zeitpunkt in s
+ * @return Funktionswert
+ */
+ private double synthesizeSine(double frequency, double timeSample)
+ {
+ return Math.sin(timeSample * frequency * Math.PI * 2);
+ }
+
+ // Die folgenden Funktionen nutzen die Fourier-Reihen der entsprechenden
+ // Wellenformen zur Berechnung der Funktionswerte. Der Algorithmus ist
+ // an das Pseudocode-Konzept (Beispiel: Rechteck/Square) angelehnt:
+ /**
+ * Funktion sq(t):
+ * funktionswert = 0;
+ * von order = 1 bis 22050/freq/2, Schritt 1:
+ * funktionswert = funktionswert +
+ * (sin(2 * PI * freq * (order * 2 - 1) * t)
+ * / (order * 2 - 1));
+ * Rückgabe von 4 / PI * funktionswert;
+ */
+
+ /**
+ * Berechnung des Funktionswertes einer Saegezahn-Funktion (Sawtooth) der Frequenz frequency zum Zeitpunkt timeSample
+ * @param frequency Frequenz in Hz
+ * @param timeSample Zeitpunkt in s
+ * @return Funktionswert
+ */
+ private double synthesizeSaw(double frequency, double timeSample)
+ {
+ double tempSample = 0;
+ for (int order = 1; order <= cutoff/frequency; order++) {
+ tempSample += (Math.sin(timeSample * frequency * order
+ * Math.PI * 2) / order);
+ }
+ return (2 / Math.PI * tempSample);
+ }
+
+ /**
+ * Berechnung des Funktionswertes einer Rechteck-Funktion (Square) der Frequenz frequency zum Zeitpunkt timeSample
+ * @param frequency Frequenz in Hz
+ * @param timeSample Zeitpunkt in s
+ * @return Funktionswert
+ */
+ private double synthesizeSquare(double frequency, double timeSample)
+ {
+ double tempSample = 0;
+ for (int order = 1; order <= cutoff/frequency/2; order++) {
+ tempSample += (Math.sin(timeSample * frequency * (order * 2 - 1)
+ * Math.PI * 2) / (order * 2 - 1));
+ }
+ return (4 / Math.PI * tempSample);
+ }
+
+ /**
+ * Berechnung des Funktionswertes einer Dreieck-Funktion (Triangle) der Frequenz frequency zum Zeitpunkt timeSample
+ * @param frequency Frequenz in Hz
+ * @param timeSample Zeitpunkt in s
+ * @return Funktionswert
+ */
+ private double synthesizeTriangle(double frequency, double timeSample)
+ {
+ double tempSample = 0;
+ for (int order = 1; order <= cutoff/frequency/2; order++) {
+ tempSample += (Math.cos(timeSample * frequency *
+ (order * 2 - 1) * Math.PI * 2))
+ / ((order * 2 - 1)*(order * 2 - 1));
+ }
+ return ((8 / (Math.PI*Math.PI)) * tempSample);
+ }
+
+ /**
+ * Methode zur Ausgabe des Funktionswertes der festgelegten Wellenform der Frequenz frequency zum Zeitpunkt timeSample
+ * @param frequency Frequenz in Hz
+ * @param timeSample Zeitpunkt in s
+ * @return Funktionswert
+ */
+ public float getSample(double frequency, double timeSample)
+ {
+ if (null != waveform) switch (waveform) {
+ case "sine":
+ return (float)synthesizeSine(frequency, timeSample);
+ case "saw":
+ return (float)synthesizeSaw(frequency, timeSample);
+ case "square":
+ return (float)synthesizeSquare(frequency, timeSample);
+ case "triangle":
+ return (float)synthesizeTriangle(frequency, timeSample);
+ default:
+ return 0;
+ } else return 0;
+ }
+}
diff --git a/Synth.java b/Synth.java
new file mode 100644
index 0000000..d0f460c
--- /dev/null
+++ b/Synth.java
@@ -0,0 +1,187 @@
+/**
+ * Synth-Klasse der Implementation von Fourier-Reihen zur Klangsynthese.
+ * Fuer die Facharbeit vom 16.03.2017
+ * Dies ist "das Herz" der Anwendung.
+ * Objekte dieser Klasse fuehren Berechnung und WAVE-Speichrung des Klanges aus.
+ * 2017, Soeren Richter
+ * soeren@dreieck-project.de
+ * Version 0.1.5
+ * Code selbst geschrieben, WAVE-Speicherung basierend auf
+ * http://stackoverflow.com/questions/3297749/java-reading-manipulating-and-writing-wav-files
+ * und Abschnitt 2.2 sowie 4 der Facharbeit.
+ * @author Soeren Richter
+ * @version 0.1.5
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import java.awt.*;
+import java.io.IOException;
+import javax.swing.*;
+
+public class Synth {
+ // Samplerate des zu erzeugenden PCM-Datenstroms:
+ private final double samplerate;
+
+ // Tonlänge exklusive Relese der Huellkurve (Hold-Zeit):
+ private final double length;
+
+ // Frequenz der zu synthetisierenden Tons:
+ private final double freq;
+
+ // relative Amplitude:
+ private final double amplitude;
+
+ // Wellenform; "sine", "saw", "square" oder "triangle":
+ private final String waveform;
+
+ // Attribute der Huellkurve:
+ private final double attack;
+ private final double decay;
+ private final double sustain;
+ private final double release;
+
+ /**
+ * Konstruktor der Synth-Klasse.
+ * @param pSamplerate Samplerate des zu erzeugenden PCM-Datenstroms
+ * @param pLength Tonlänge exklusive Relese der Huellkurve (Hold-Zeit)
+ * @param pFreq Frequenz der zu synthetisierenden Tons
+ * @param pAmp relative Amplitude
+ * @param pWaveform Wellenform ("sine", "saw", "square" oder "triangle")
+ * @param pAttack Attack-Zeit der Huellkurve
+ * @param pDecay Decay-Zeit der Huellkurve
+ * @param pSustain Sustain-Amplitude der Huellkurve
+ * @param pRelease Release-Zeit der Huellkurve
+ */
+ public Synth(double pSamplerate, double pLength, double pFreq, double pAmp,
+ String pWaveform, double pAttack, double pDecay, double pSustain,
+ double pRelease) {
+ samplerate = pSamplerate;
+ length = pLength;
+ freq = pFreq;
+ amplitude = pAmp;
+ waveform = pWaveform;
+ attack = pAttack;
+ decay = pDecay;
+ sustain = pSustain;
+ release = pRelease;
+ }
+
+ /**
+ * Methode zur Durchfuehrung der Klangsynthese.
+ */
+ public void synthesize_standard() {
+ // Die Zeildatei der Synthese wird nach Auswahl festgelegt.
+ File filePath = getFilePath();
+
+ // Wenn eine Datei gewaehlt wurde, wird die Klangsynthese
+ // durchgefuehrt, ansonsten mit entsprechendem Hinweis nicht.
+ if (filePath != null) {
+ // Oscillator- und Envelope-Objekt werden den jeweils
+ // festgelegten konstanten Attributen erzeugt.
+ Oscillator osc = new Oscillator(waveform, (int)samplerate/2);
+ Envelope env = new Envelope(attack,decay,sustain,release);
+
+ // Hold-Laenge des Tons wird an das Envelope-Objekt uebergeben.
+ env.setLength(length);
+
+ // Fliesskomma-Array buffer zur Aufnahme der
+ // berechneten Werte wird erzeugt.
+ float[] buffer = new float[(int)(samplerate * env.getFullLength())];
+
+ // Werteberechnung der synthetisierten Schallwelle wird
+ // entsprechend Pseudocode-Konzept durchgefuehrt, siehe:
+ /**
+ * von sample = 0 bis 44100 * (length + release), Schritt 1:
+ * schreibe amp * rect(sample/44100) * env(sample/44100);
+ */
+ for (int sample = 0; sample < buffer.length; sample++) {
+ buffer[sample] = (float)(osc.getSample(freq, sample / samplerate)
+ * env.getAmplitude(sample / samplerate)
+ * amplitude);
+ }
+
+ // Der Fliesskomma-Buffer wird an die Speichermethode weitergegeben.
+ save_as_wave(buffer, filePath);
+
+ } else {
+ JOptionPane.showMessageDialog(new JFrame("Info"),
+ "Es wurde keine Datei geschrieben.");
+ }
+
+ }
+
+ /**
+ * Methode, die die Fliesskommareihe sampleBuffer in einen 16-Bit PCM Datenstrom konvertiert und als WAVE-Datei nach outputFile speichert.
+ * @param sampleBuffer Umzuwandelnde Fliesskommareihe
+ * @param outputFile Zieldatei der WAV-Speicherung
+ */
+ private void save_as_wave(float[] sampleBuffer, File outputFile) {
+ // Erstellung eines Byte-Arrays zur Aufnahme der 16-Bit PCM-Werte.
+ // Fuer jeden Datenwert werden 2 Byte (2*8 Bit) benötigt. Daher muss
+ // der Byte-Buffer doppelt so lang sein, wie der bisherige Buffer.
+ final byte[] byteBuffer = new byte[sampleBuffer.length * 2];
+
+ int bufferIndex = 0;
+
+ // Umwandlung der Fliesskommawerte in einen 16-Bit Datenstrom, der
+ // aus jeweils zwei Byte (8-Bit) Werten für jeden PCM-Wert besteht.
+ // Jeder zweite Wert wird vor der Zuweisung um 8 Bit-Stellen verschoben.
+ for (int i = 0; i < byteBuffer.length; i++) {
+ final int x = (int) (sampleBuffer[bufferIndex++] * 32767.0);
+ byteBuffer[i] = (byte) x;
+ i++;
+ byteBuffer[i] = (byte) (x >>> 8);
+ }
+
+ // Nutzung der javax.sound.sampled-API zum Schreiben des Byte-Buffers
+ // in eine WAVE-Datei outputFile mit korrektem Header. Moegliche
+ // Probleme bei der Speicherung werden abgefangen.
+ try {
+ AudioFormat format = new AudioFormat((float)samplerate, 16, 1,
+ true, false);
+ ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer);
+
+ try (AudioInputStream audioInputStream = new AudioInputStream(bais,
+ format, sampleBuffer.length)) {
+ AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE,
+ outputFile);
+ }
+
+ JOptionPane.showMessageDialog(new JFrame("Info"),
+ "Die WAV-Datei wurde erfolgreich generiert und nach "
+ + outputFile + " geschrieben.");
+
+ } catch (HeadlessException | IOException e) {
+ JOptionPane.showMessageDialog(new JFrame("Info"),
+ "Es wurde keine Datei geschrieben, da folgender Fehler auftrat: "
+ + e);
+ }
+ }
+
+ /**
+ * Methode zur Auswahl einer Zieldatei
+ * @return Pfad der WAVE-Zieldatei
+ */
+ private File getFilePath() {
+ // Dateiwahldialog wird aufgerufen.
+ JFileChooser fc = new JFileChooser();
+ int returnVal = fc.showOpenDialog(new JFrame("parent"));
+
+ // Wurde eine Datei gewaehlt, wird diese zurueckgegeben. Falls die
+ // Endung ".wav" bisher fehlte, wird diese zusaetzlich angefuegt.
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ if (fc.getSelectedFile().toString().endsWith(".wav"))
+ return fc.getSelectedFile();
+ else {
+ return new File(fc.getSelectedFile().toString() + ".wav");
+ }
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/mainWindow.form b/mainWindow.form
new file mode 100644
index 0000000..03bf24e
--- /dev/null
+++ b/mainWindow.form
@@ -0,0 +1,771 @@
+
+
+
diff --git a/mainWindow.java b/mainWindow.java
new file mode 100644
index 0000000..10b541e
--- /dev/null
+++ b/mainWindow.java
@@ -0,0 +1,844 @@
+/**
+ * mainWindow-Klasse.
+ * Diese Klasse beherbergt die graphische Benutzeroberfläche und Ereignisse dieser.
+ * 2017, Soeren Richter
+ * soeren@dreieck-project.de
+ * Version 0.1.5
+ * Code vollstaendig selbst geschrieben, fuer Hintergruende und
+ * Referenzen siehe Abschnitt 4 der Facharbeit.
+ * @author Soeren Richter
+ * @version 0.1.5
+ */
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import java.util.Random;
+
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+/**
+ *
+ * @author Soeren Richter
+ */
+public class mainWindow extends javax.swing.JFrame {
+
+ /**
+ * Creates new form mainWindow
+ */
+ public mainWindow() {
+ initComponents();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jButton1 = new javax.swing.JButton();
+ jPanel1 = new javax.swing.JPanel();
+ sineRad = new javax.swing.JRadioButton();
+ sawRad = new javax.swing.JRadioButton();
+ squareRad = new javax.swing.JRadioButton();
+ triangleRad = new javax.swing.JRadioButton();
+ jLabel8 = new javax.swing.JLabel();
+ lenSpinner = new javax.swing.JSpinner();
+ jLabel9 = new javax.swing.JLabel();
+ jPanel2 = new javax.swing.JPanel();
+ jLabel7 = new javax.swing.JLabel();
+ jLabel11 = new javax.swing.JLabel();
+ jLabel12 = new javax.swing.JLabel();
+ jLabel13 = new javax.swing.JLabel();
+ jLabel15 = new javax.swing.JLabel();
+ amplFact = new javax.swing.JSpinner();
+ jPanel5 = new javax.swing.JPanel();
+ attackSlider = new javax.swing.JSlider();
+ decaySlider = new javax.swing.JSlider();
+ sustainSlider = new javax.swing.JSlider();
+ releaseSlider = new javax.swing.JSlider();
+ aLabel = new javax.swing.JLabel();
+ dLabel = new javax.swing.JLabel();
+ sLabel = new javax.swing.JLabel();
+ rLabel = new javax.swing.JLabel();
+ jPanel3 = new javax.swing.JPanel();
+ jLabel3 = new javax.swing.JLabel();
+ jLabel4 = new javax.swing.JLabel();
+ keyPitch = new javax.swing.JSpinner();
+ freqPitch = new javax.swing.JSpinner();
+ centPitch = new javax.swing.JSpinner();
+ jRadioButton1 = new javax.swing.JRadioButton();
+ jRadioButton2 = new javax.swing.JRadioButton();
+ jPanel4 = new javax.swing.JPanel();
+ jLabel5 = new javax.swing.JLabel();
+ jLabel6 = new javax.swing.JLabel();
+ srBox = new javax.swing.JComboBox<>();
+ jComboBox2 = new javax.swing.JComboBox<>();
+ jButton2 = new javax.swing.JButton();
+ jButton3 = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ setTitle("Fourier-Synthesizer Implementation Facharbeit Sören Richter");
+ setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+ setResizable(false);
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowOpened(java.awt.event.WindowEvent evt) {
+ formWindowOpened(evt);
+ }
+ });
+
+ jButton1.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jButton1.setText("WAVE-Datei generieren und speichern unter");
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton1ActionPerformed(evt);
+ }
+ });
+
+ jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Wellenform", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12))); // NOI18N
+ jPanel1.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+
+ sineRad.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ sineRad.setSelected(true);
+ sineRad.setText("Sinus");
+ sineRad.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ sineRadActionPerformed(evt);
+ }
+ });
+
+ sawRad.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ sawRad.setText("Sägezahn");
+ sawRad.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ sawRadActionPerformed(evt);
+ }
+ });
+
+ squareRad.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ squareRad.setText("Rechteck");
+ squareRad.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ squareRadActionPerformed(evt);
+ }
+ });
+
+ triangleRad.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ triangleRad.setText("Dreieck");
+ triangleRad.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ triangleRadActionPerformed(evt);
+ }
+ });
+
+ jLabel8.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel8.setText("Länge:");
+
+ lenSpinner.setModel(new javax.swing.SpinnerNumberModel(1.0d, 0.0d, 60.0d, 0.1d));
+ lenSpinner.setName(""); // NOI18N
+ lenSpinner.setValue(1);
+
+ jLabel9.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel9.setText("sec");
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(15, 15, 15)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addComponent(jLabel8)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(lenSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jLabel9))
+ .addComponent(sineRad)
+ .addComponent(sawRad)
+ .addComponent(squareRad)
+ .addComponent(triangleRad))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(sineRad)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(sawRad)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(squareRad)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(triangleRad)
+ .addGap(18, 18, 18)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel8)
+ .addComponent(lenSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel9))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Hüllkurve", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12))); // NOI18N
+ jPanel2.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+
+ jLabel7.setFont(new java.awt.Font("Segoe UI", 0, 18)); // NOI18N
+ jLabel7.setText("A");
+
+ jLabel11.setFont(new java.awt.Font("Segoe UI", 0, 18)); // NOI18N
+ jLabel11.setText("D");
+
+ jLabel12.setFont(new java.awt.Font("Segoe UI", 0, 18)); // NOI18N
+ jLabel12.setText("S");
+
+ jLabel13.setFont(new java.awt.Font("Segoe UI", 0, 18)); // NOI18N
+ jLabel13.setText("R");
+
+ jLabel15.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel15.setText("Amplitudenfaktor");
+
+ amplFact.setModel(new javax.swing.SpinnerNumberModel(0.8d, 0.0d, 1.0d, 0.05d));
+
+ attackSlider.setMaximum(1000);
+ attackSlider.setValue(100);
+ attackSlider.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ attackSliderMouseClicked(evt);
+ }
+ });
+ attackSlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ attackSliderPropertyChange(evt);
+ }
+ });
+
+ decaySlider.setMaximum(1000);
+ decaySlider.setValue(100);
+ decaySlider.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ decaySliderMouseClicked(evt);
+ }
+ });
+ decaySlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ decaySliderPropertyChange(evt);
+ }
+ });
+
+ sustainSlider.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ sustainSliderMouseClicked(evt);
+ }
+ });
+ sustainSlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ sustainSliderPropertyChange(evt);
+ }
+ });
+
+ releaseSlider.setMaximum(1000);
+ releaseSlider.setValue(100);
+ releaseSlider.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ releaseSliderMouseClicked(evt);
+ }
+ });
+ releaseSlider.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ releaseSliderPropertyChange(evt);
+ }
+ });
+
+ javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
+ jPanel5.setLayout(jPanel5Layout);
+ jPanel5Layout.setHorizontalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel5Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel5Layout.createSequentialGroup()
+ .addGap(0, 0, Short.MAX_VALUE)
+ .addComponent(decaySlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(jPanel5Layout.createSequentialGroup()
+ .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(attackSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(sustainSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(releaseSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(0, 0, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ jPanel5Layout.setVerticalGroup(
+ jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel5Layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(attackSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(decaySlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(sustainSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(releaseSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ aLabel.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ aLabel.setText("100 ms");
+
+ dLabel.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ dLabel.setText("100 ms");
+
+ sLabel.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ sLabel.setText("50%");
+
+ rLabel.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ rLabel.setText("100 ms");
+
+ javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+ jPanel2.setLayout(jPanel2Layout);
+ jPanel2Layout.setHorizontalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addGap(18, 18, 18)
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addComponent(jLabel15)
+ .addGap(18, 18, 18)
+ .addComponent(amplFact, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel7)
+ .addComponent(jLabel11)
+ .addComponent(jLabel12)
+ .addComponent(jLabel13))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(aLabel)
+ .addComponent(dLabel)
+ .addComponent(sLabel)
+ .addComponent(rLabel))))
+ .addContainerGap(19, Short.MAX_VALUE))
+ );
+ jPanel2Layout.setVerticalGroup(
+ jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addGap(4, 4, 4)
+ .addComponent(aLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(dLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(sLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(rLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGap(67, 67, 67))
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addComponent(jLabel7)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel11)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel12)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel13)
+ .addGap(26, 26, 26)
+ .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel15)
+ .addComponent(amplFact, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+ .addGroup(jPanel2Layout.createSequentialGroup()
+ .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(51, 51, 51))
+ );
+
+ jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Tonhöhe", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12))); // NOI18N
+ jPanel3.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+
+ jLabel3.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel3.setText("+");
+
+ jLabel4.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel4.setText("cents");
+
+ keyPitch.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ keyPitch.setModel(new javax.swing.SpinnerNumberModel(0.0d, -66.0d, 66.0d, 1.0d));
+ keyPitch.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ keyPitchPropertyChange(evt);
+ }
+ });
+
+ freqPitch.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ freqPitch.setModel(new javax.swing.SpinnerNumberModel(440.0d, 0.0d, 20000.0d, 0.1d));
+ freqPitch.setEnabled(false);
+ freqPitch.setValue(440.0);
+ freqPitch.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ freqPitchPropertyChange(evt);
+ }
+ });
+
+ centPitch.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ centPitch.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 100.0d, 0.1d));
+ centPitch.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+ public void propertyChange(java.beans.PropertyChangeEvent evt) {
+ centPitchPropertyChange(evt);
+ }
+ });
+
+ jRadioButton1.setSelected(true);
+ jRadioButton1.setText("Ton (a1 = 0)");
+ jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jRadioButton1ActionPerformed(evt);
+ }
+ });
+
+ jRadioButton2.setText("Freq. / Hz");
+ jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jRadioButton2ActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
+ jPanel3.setLayout(jPanel3Layout);
+ jPanel3Layout.setHorizontalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGap(33, 33, 33)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addComponent(jLabel3)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(centPitch, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jLabel4))
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addComponent(keyPitch, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(freqPitch, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE))))
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGap(14, 14, 14)
+ .addComponent(jRadioButton1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jRadioButton2)))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ jPanel3Layout.setVerticalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGap(8, 8, 8)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jRadioButton1)
+ .addComponent(jRadioButton2))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(keyPitch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(freqPitch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel3)
+ .addComponent(centPitch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel4))
+ .addContainerGap(22, Short.MAX_VALUE))
+ );
+
+ jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "PCM/WAVE-Parameter", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Segoe UI", 0, 12))); // NOI18N
+ jPanel4.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+
+ jLabel5.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel5.setText("Samplerate");
+
+ jLabel6.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jLabel6.setText("Bits/Sample");
+ jLabel6.setEnabled(false);
+
+ srBox.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ srBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "8000", "11025", "16000", "22050", "32000", "44100", "48000", "88200", "96000" }));
+ srBox.setSelectedIndex(5);
+
+ jComboBox2.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jComboBox2.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "8", "16", "24", "32" }));
+ jComboBox2.setSelectedIndex(1);
+ jComboBox2.setSelectedItem(1);
+ jComboBox2.setEnabled(false);
+
+ javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
+ jPanel4.setLayout(jPanel4Layout);
+ jPanel4Layout.setHorizontalGroup(
+ jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(srBox, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(27, 27, 27)
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(jComboBox2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(29, 29, 29))
+ );
+ jPanel4Layout.setVerticalGroup(
+ jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel4Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel5)
+ .addComponent(jLabel6))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(srBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ jButton2.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jButton2.setText("Parameter zufällig setzen");
+ jButton2.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton2ActionPerformed(evt);
+ }
+ });
+
+ jButton3.setFont(new java.awt.Font("Segoe UI", 0, 12)); // NOI18N
+ jButton3.setText("Programminfo");
+ jButton3.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jButton3ActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 177, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 269, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jButton1)
+ .addComponent(jButton2)
+ .addComponent(jButton3))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+ Thread.yield();
+
+ final String tempWaveform;
+
+ if (sineRad.isSelected()) {
+ tempWaveform = "sine";
+ } else if (sawRad.isSelected()) {
+ tempWaveform = "saw";
+ } else if (squareRad.isSelected()) {
+ tempWaveform = "square";
+ } else if (triangleRad.isSelected()) {
+ tempWaveform = "triangle";
+ } else {
+ tempWaveform = "sine";
+ }
+
+ java.awt.EventQueue.invokeLater(() -> {
+ Synth gen = new Synth(Double.parseDouble((String) srBox.getSelectedItem()),
+ (double)lenSpinner.getValue(),
+ (double)freqPitch.getValue(),
+ (double)amplFact.getValue(),
+ tempWaveform,
+ attackSlider.getValue() / 1000.0,
+ decaySlider.getValue() / 1000.0,
+ sustainSlider.getValue() / 100.0,
+ releaseSlider.getValue() / 1000.0);
+ gen.synthesize_standard();
+ });
+ }//GEN-LAST:event_jButton1ActionPerformed
+
+ private void sineRadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sineRadActionPerformed
+ sawRad.setSelected(false);
+ squareRad.setSelected(false);
+ triangleRad.setSelected(false);
+ }//GEN-LAST:event_sineRadActionPerformed
+
+ private void attackSliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_attackSliderPropertyChange
+ aLabel.setText(attackSlider.getValue() + " ms");
+ }//GEN-LAST:event_attackSliderPropertyChange
+
+ private void decaySliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_decaySliderPropertyChange
+ dLabel.setText(decaySlider.getValue() + " ms");
+ }//GEN-LAST:event_decaySliderPropertyChange
+
+ private void sustainSliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_sustainSliderPropertyChange
+ sLabel.setText(sustainSlider.getValue() + "%");
+ }//GEN-LAST:event_sustainSliderPropertyChange
+
+ private void releaseSliderPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_releaseSliderPropertyChange
+ rLabel.setText(releaseSlider.getValue() + " ms");
+ }//GEN-LAST:event_releaseSliderPropertyChange
+
+ private void sawRadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sawRadActionPerformed
+ sineRad.setSelected(false);
+ squareRad.setSelected(false);
+ triangleRad.setSelected(false);
+ }//GEN-LAST:event_sawRadActionPerformed
+
+ private void squareRadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_squareRadActionPerformed
+ sawRad.setSelected(false);
+ sineRad.setSelected(false);
+ triangleRad.setSelected(false);
+ }//GEN-LAST:event_squareRadActionPerformed
+
+ private void triangleRadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_triangleRadActionPerformed
+ sawRad.setSelected(false);
+ squareRad.setSelected(false);
+ sineRad.setSelected(false);
+ }//GEN-LAST:event_triangleRadActionPerformed
+
+ private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
+ Random r = new Random();
+
+ switch (r.nextInt(4)){
+ case 0:
+ sineRad.setSelected(true);
+ sawRad.setSelected(false);
+ squareRad.setSelected(false);
+ triangleRad.setSelected(false);
+ break;
+ case 1:
+ sineRad.setSelected(false);
+ sawRad.setSelected(true);
+ squareRad.setSelected(false);
+ triangleRad.setSelected(false);
+ break;
+ case 2:
+ sineRad.setSelected(false);
+ sawRad.setSelected(false);
+ squareRad.setSelected(true);
+ triangleRad.setSelected(false);
+ break;
+ case 3:
+ sineRad.setSelected(false);
+ sawRad.setSelected(false);
+ squareRad.setSelected(false);
+ triangleRad.setSelected(true);
+ break;
+ }
+
+ freqPitch.setValue(r.nextDouble()*20000.0);
+ lenSpinner.setValue(r.nextDouble());
+ attackSlider.setValue(r.nextInt(1001));
+ decaySlider.setValue(r.nextInt(1001));
+ sustainSlider.setValue(r.nextInt(101));
+ releaseSlider.setValue(r.nextInt(1001));
+ amplFact.setValue(r.nextDouble());
+
+ aLabel.setText(attackSlider.getValue() + " ms");
+ dLabel.setText(decaySlider.getValue() + " ms");
+ sLabel.setText(sustainSlider.getValue() + "%");
+ rLabel.setText(releaseSlider.getValue() + " ms");
+ keyPitch.setValue(pitch.key((double) freqPitch.getValue())
+ - pitch.key((double) freqPitch.getValue()) % 1);
+ centPitch.setValue((pitch.key((double) freqPitch.getValue())
+ % 1) * 100);
+
+ Thread.yield();
+ }//GEN-LAST:event_jButton2ActionPerformed
+
+ private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
+ JOptionPane.showMessageDialog(new JFrame("Programminfo"),
+ "Referenz-Implementation eines Fourier-"
+ + "Synthesizers für die Facharbeit vom "
+ + "16.03.2017\n"
+ + "2016-2017, Sören Richter\n"
+ + "Version: 0.1.5");
+ }//GEN-LAST:event_jButton3ActionPerformed
+
+ private void jRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton1ActionPerformed
+ if (jRadioButton1.isSelected()){
+ freqPitch.setEnabled(false);
+ jRadioButton2.setSelected(false);
+ keyPitch.setEnabled(true);
+ centPitch.setEnabled(true);
+ }
+ }//GEN-LAST:event_jRadioButton1ActionPerformed
+
+ private void jRadioButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButton2ActionPerformed
+ if (jRadioButton2.isSelected()){
+ keyPitch.setEnabled(false);
+ centPitch.setEnabled(false);
+ jRadioButton1.setSelected(false);
+ freqPitch.setEnabled(true);
+ }
+ }//GEN-LAST:event_jRadioButton2ActionPerformed
+
+ private void freqPitchPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_freqPitchPropertyChange
+ if (evt.getSource()==freqPitch){
+ keyPitch.setValue(pitch.key((double) freqPitch.getValue())
+ - pitch.key((double) freqPitch.getValue()) % 1);
+ centPitch.setValue((pitch.key((double) freqPitch.getValue())
+ % 1) * 100);
+ }
+ }//GEN-LAST:event_freqPitchPropertyChange
+
+ private void keyPitchPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_keyPitchPropertyChange
+ if (evt.getSource()==keyPitch){
+ freqPitch.setValue(pitch.freq((double) keyPitch.getValue()
+ + (double) centPitch.getValue() / 100.0));
+ }
+ }//GEN-LAST:event_keyPitchPropertyChange
+
+ private void centPitchPropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_centPitchPropertyChange
+ if (evt.getSource()==centPitch){
+ freqPitch.setValue(pitch.freq((double) keyPitch.getValue()
+ + (double) centPitch.getValue() / 100.0));
+ }
+ }//GEN-LAST:event_centPitchPropertyChange
+
+ private void attackSliderMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_attackSliderMouseClicked
+ aLabel.setText(attackSlider.getValue() + " ms");
+ }//GEN-LAST:event_attackSliderMouseClicked
+
+ private void decaySliderMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_decaySliderMouseClicked
+ dLabel.setText(decaySlider.getValue() + " ms");
+ }//GEN-LAST:event_decaySliderMouseClicked
+
+ private void sustainSliderMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_sustainSliderMouseClicked
+ sLabel.setText(sustainSlider.getValue() + "%");
+ }//GEN-LAST:event_sustainSliderMouseClicked
+
+ private void releaseSliderMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_releaseSliderMouseClicked
+ rLabel.setText(releaseSlider.getValue() + " ms");
+ }//GEN-LAST:event_releaseSliderMouseClicked
+
+ private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
+ keyPitch.setValue(0.0);
+ centPitch.setValue(0.0);
+ freqPitch.setValue(440.0);
+ lenSpinner.setValue(0.9);
+ attackSlider.setValue(100);
+ decaySlider.setValue(100);
+ sustainSlider.setValue(50);
+ releaseSlider.setValue(100);
+ amplFact.setValue(0.8);
+
+ Thread.yield();
+ }//GEN-LAST:event_formWindowOpened
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+// for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+// if ("Nimbus".equals(info.getName())) {
+// javax.swing.UIManager.setLookAndFeel(info.getClassName());
+// break;
+// }
+// }
+ javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(mainWindow.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(() -> {
+ new mainWindow().setVisible(true);
+ });
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel aLabel;
+ private javax.swing.JSpinner amplFact;
+ private javax.swing.JSlider attackSlider;
+ private javax.swing.JSpinner centPitch;
+ private javax.swing.JLabel dLabel;
+ private javax.swing.JSlider decaySlider;
+ private javax.swing.JSpinner freqPitch;
+ private javax.swing.JButton jButton1;
+ private javax.swing.JButton jButton2;
+ private javax.swing.JButton jButton3;
+ private javax.swing.JComboBox jComboBox2;
+ private javax.swing.JLabel jLabel11;
+ private javax.swing.JLabel jLabel12;
+ private javax.swing.JLabel jLabel13;
+ private javax.swing.JLabel jLabel15;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JLabel jLabel4;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JLabel jLabel6;
+ private javax.swing.JLabel jLabel7;
+ private javax.swing.JLabel jLabel8;
+ private javax.swing.JLabel jLabel9;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPanel jPanel2;
+ private javax.swing.JPanel jPanel3;
+ private javax.swing.JPanel jPanel4;
+ private javax.swing.JPanel jPanel5;
+ private javax.swing.JRadioButton jRadioButton1;
+ private javax.swing.JRadioButton jRadioButton2;
+ private javax.swing.JSpinner keyPitch;
+ private javax.swing.JSpinner lenSpinner;
+ private javax.swing.JLabel rLabel;
+ private javax.swing.JSlider releaseSlider;
+ private javax.swing.JLabel sLabel;
+ private javax.swing.JRadioButton sawRad;
+ private javax.swing.JRadioButton sineRad;
+ private javax.swing.JRadioButton squareRad;
+ private javax.swing.JComboBox srBox;
+ private javax.swing.JSlider sustainSlider;
+ private javax.swing.JRadioButton triangleRad;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/pitch.java b/pitch.java
new file mode 100644
index 0000000..55a88ff
--- /dev/null
+++ b/pitch.java
@@ -0,0 +1,33 @@
+/**
+ * Statische Klasse zur Frequenz-/Halbtonumrechnung in der gleichstufigen Stimmung
+ * Fuer die Facharbeit vom 16.03.2017
+ * 2017, Soeren Richter
+ * soeren@dreieck-project.de
+ * Version 0.1.5
+ * Auf Grundlage von Abschnitt 2.3 der Facharbeit.
+ * @author Soeren Richter
+ * @version 0.1.5
+ */
+
+public class pitch
+{
+ /**
+ * Rechnet Halbtonschritte von a aus zu Frequenzwert in Hz um.
+ * @param key Halbtonschritte vom Kammerton a aus
+ * @return Frequenz in Hz
+ */
+ public static double freq(double key)
+ {
+ return Math.pow(2.0, key/12.0)*440.0;
+ }
+
+ /**
+ * Rechnet Frequenzwert in Hz zu Halbtonschritten von a aus um.
+ * @param freq Frequenz in Hz
+ * @return Halbtonschritte vom Kammerton a aus
+ */
+ public static double key(double freq)
+ {
+ return (Math.log(freq/440.0)/Math.log(2.0))*12.0;
+ }
+}