import numpy as np
SAMPLE_RATE = 44100
def sound():
duration = 2
t = np.linspace(
0,
duration,
int(SAMPLE_RATE * duration),
False
)
freq = 440
signal = (
1.0 * np.sin(2 * np.pi * freq * t)
+ 0.8 * np.sin(2 * np.pi * freq * 2 * t)
+ 0.6 * np.sin(2 * np.pi * freq * 3 * t)
+ 0.4 * np.sin(2 * np.pi * freq * 4 * t)
+ 0.2 * np.sin(2 * np.pi * freq * 5 * t)
)
env = np.ones(len(signal))
fade_in = int(0.02 * SAMPLE_RATE)
fade_out = int(0.20 * SAMPLE_RATE)
env[:fade_in] = np.linspace(
0,
1,
fade_in
)
env[-fade_out:] = np.linspace(
1,
0,
fade_out
)
signal *= env
signal /= np.max(np.abs(signal))
return signal * 0.3
1. Abtastrate
SAMPLE_RATE = 44100
Erklärung
Die Abtastrate legt fest, wie viele Messwerte pro Sekunde berechnet werden. Eine Abtastrate von 44.100 Hz entspricht CD-Qualität. Für einen zwei Sekunden langen Ton werden somit 88.200 Samples erzeugt.
2. Dauer
duration = 2
Erklärung
Hier wird festgelegt, dass der Ton zwei Sekunden lang sein soll.
3. Zeitachse
t = np.linspace(
0,
duration,
int(SAMPLE_RATE * duration),
False
)
Erklärung
np.linspace() erzeugt die Zeitachse.
Für jeden einzelnen Sample wird der genaue Zeitpunkt berechnet.
Diese Werte werden später für die Sinusfunktion verwendet.
4. Frequenz
freq = 440
Erklärung
440 Hz entspricht dem musikalischen Ton A4 (Kammerton A). Die Schwingung wiederholt sich 440-mal pro Sekunde.
5. Sinuswellen
signal = (
...
)
Erklärung
Hier werden fünf Sinuswellen addiert:
- Grundton: 440 Hz
- 2. Oberton: 880 Hz
- 3. Oberton: 1320 Hz
- 4. Oberton: 1760 Hz
- 5. Oberton: 2200 Hz
Durch unterschiedliche Lautstärken der Obertöne entsteht ein komplexerer Klang als bei einer einzelnen Sinuswelle.
6. Hüllkurve
env = np.ones(len(signal))
Erklärung
Die Hüllkurve steuert die Lautstärke über die Zeit. Zunächst besitzt jeder Sample den Wert 1, wodurch das Signal unverändert bleibt.
7. Fade-In und Fade-Out
fade_in = int(0.02 * SAMPLE_RATE)
fade_out = int(0.20 * SAMPLE_RATE)
Erklärung
Am Anfang wird der Ton innerhalb von 20 ms langsam eingeblendet. Am Ende wird er innerhalb von 200 ms ausgeblendet. Dadurch entstehen keine hörbaren Knackgeräusche.
8. Hüllkurve anwenden
signal *= env
Erklärung
Jeder Sample des Tons wird mit dem entsprechenden Wert der Hüllkurve multipliziert. Dadurch verändert sich die Lautstärke über die Zeit.
9. Normalisierung
signal /= np.max(np.abs(signal))
Erklärung
Durch die Addition mehrerer Sinuswellen können Werte größer als 1 entstehen. Die Normalisierung skaliert das Signal so, dass die maximale Amplitude wieder genau 1 beträgt und kein Clipping auftritt.
10. Lautstärke
return signal * 0.3
Erklärung
Zum Schluss wird die Gesamtlautstärke auf 30 % reduziert. Dadurch bleibt die Form der Wellen unverändert, der Ton wird lediglich leiser.