Sound - Institut für Informatik

Transcription

Sound - Institut für Informatik
Kapitel 10:
Signalverarbeitung mit Python: Sound
Einführung in die Informatik
Wintersemester 2007/08
Prof. Bernhard Jung
Übersicht
Signalverarbeitung mit Python: Sound
‰
‰
Repräsentation von Sound
Algorithmen:
„
„
„
„
Erhöhen der Lautstärke
Normalisierung von Sound
Rückwärts-Sound
Konkatenierung von Sound
„
Kombination von Sounds
‰
‰
„
„
Akkorde
Echo
Synthetischer Sound
Frequenz von Sounds erhöhen
/ verringern
Hauptlernziele
• Repräsentation von digitalem Sound verstehen
• Digitalen Sound als eine Art von Messwerten verstehen
• Einfache Python-Programme zur Soundverarbeitung entwickeln können
• Wdh: Schleifen (for) und bedingte Anweisungen (if … else) verstehen
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
1
Akustik – die Lehre vom Schall
„
„
Schallwellen sind zyklisch
Frequenz einer Welle
‰
‰
„
Anzahl der Zyklen pro Sekunde
gemessen in Hertz
(1 Hz = 1 Zyklus / Sekunde)
Amplitude
Amplitude
‰
maximale Höhe der Welle
1 Zyklus
„
Natürlich vorkommende Klänge
bestehen aus Überlagerung einer
Vielzahl von Schallwellen
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Psychoakustik – Wahrnehmung von Schall
Lautstärke und Tonhöhe
„
Wahrgenommene Lautstärke korreliert (logarithmisch) mit Amplitude
‰
‰
Verdopplung der Amplitude Æ ca. 3 Dezibel lauter
Dezibel: Maß für wahrgenommene Lautstärke
„
„
„
„
0 dB: Schwellwert für Wahrnehmbarkeit von Geräuschen
60 dB: Unterhaltungsgespräch
80 dB: Schreien
Wahrgenommene Tonhöhe korreliert (logarithmisch) mit Frequenz
‰
‰
‰
Höhere Frequenz Æ größere Tonhöhe
Verdopplung der Frequenz Æ 1 Oktave höher
Menschliches Gehör: 5 Hz – 20.000 Hz
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
2
Digitalisierung von Sound
„
Sound Sample
‰
‰
„
numerische Repräsentation der
Amplitude zu einem bestimmten
Zeitpunkt
(Messung des Drucks, den SoundWelle an Mikrofonmembran
erzeugt)
Æ Beschreibung der Sound-Welle
durch hinreichende Anzahl von
Samples
‰
AD-Wandler (Analog-Digital)
‰
wie viele Samples notwendig?
Prof. B. Jung
PCM – Pulse Code Modulation:
Digitale Repräsentation eines analogen
Signals, bei welcher das Signal in uniformen
Intervallen abgetastet wird und die Signalgröße in digitaler Form quantisiert wird
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Theorem von Nyquist
„
Theorem von Nyquist (bezogen auf Sound):
Zur Repräsentation (und späteren Wiedergabe) von Sound
mit maximaler Frequenz n Hertz
müssen mindestens 2n Samples abgenommen werden
„
Sampling Rate: Anzahl der erfassten Samples pro Sekunde
‰
z.B. Menschliche Stimmen: maximale Frequenz 4000 Hz
‰
z.B. Menschliches Gehör: maximale Frequenz ca. 22000 Hz
„
„
„
„
Prof. B. Jung
Æ 8000 Samples pro Sekunde notwendig (Telefon)
Æ ca. 44000 Samples pro Sekunde notwendig
Æ CD-Qualität: 44.100 Samples / Sekunde
Æ 3-Minuten Song benötigt 158.760.000 Samples (Stereo × 2)
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
3
Digitaler Sound: Repräsentation von Sound in
Computern
„
Typischerweise jeder Sample-Wert wird durch 2 Byte repräsentiert
‰
‰
‰
‰
„
Digitaler Sound = Feld (Array) von Sound-Samples
‰
„
2 Byte = 16 Bit
d.h. 216 = 65.536 verschiedene Zahlen darstellbar
Æ Sample-Werte: -32.768 … 32.767
Bem: Viele Varianten möglich, z.B. 8 Bit pro Sample
Achtung: Komprimierte Speicherung in üblichen Datei-Formaten (z.B. mp3)
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
Digitale Soundverarbeitung = Manipulation von Feldern
‰
‰
Ändern der Sample-Werte
Ändern der Feldgröße
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
WAVE-Dateiformat
„
„
„
„
Teil von Microsofts RIFFSpezifikation für
Multimedia Dateien
Repräsentation von
Samplewerten und
Formatinformationen
größtenteils als "little
endian"
z.B. Bytefolge
24 17 1e 13
repräsentiert
Hex-Zahl 0x131e1724
= 320739108
Falls 16 Bits per
Sample, werden
Samplewerte
vorzeichenbehaftet (im
Zweierkomplement)
gespeichert, d.h.
Wertebereich
-32768 … 32767
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Quelle: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
4
WAVE-Dateiformat / Beispiel
Mono = 1, Stereo =2
0x00000824 = 2084
0x5622 = 22050
0x0d1ace11
= 219860497
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Quelle: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
TUBAFSound.py
Funktionen für die Sound-Verarbeitung
„
„
Skript mit Funktionen zur einfachen Verarbeitung von digitalem Sound
Einschränkungen an Sound-Dateien
‰
‰
‰
‰
.wav Format
16 Bit Sample-Breite
mono (laden von Stereo ok)
bevorzugte Samplingrate 22050
„
„
from TUBAFSound import *
sound = makeSound('c4.wav')
playSound(sound)
saveSound(sound,'c4-copy.wav')
Verwendung
‰
‰
Skript auf Kurs-Webseite
Speichern im Arbeitsverzeichnis
„
„
„
funktioniert aber auch mit
anderen Samplingrates
>>>
>>>
>>>
>>>
mit eigenen Skripten
Sound-Dateien
Abspielen von Sound nur auf Windows u. Linux
‰
alle Plattformen: Bearbeiteten Sound speichern, dann mit geeignetem Player
abspielen
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
5
TUBAF Sound: Funktionen für die Sound-Verarbeitung
(Auswahl)
„
Öffnen von Sound-Dateien
‰
makeSound(dateiname) – Erzeugt internes Sound-Objekt
„
„
Lesen und Setzen von Sample-Werten
‰
‰
‰
‰
‰
„
nur .wav Dateien !
getSamples(sound) – liefert Liste aller Samplewerte
setSamples(sound, samples) – setzt die Samplewerte
getSample(sound, index) – liefert Wert eines Samples (als Integer-Zahl)
setSample(sound, index, value) – setzt Wert eines Samples
getLength(sound) bzw len(sound) – liefert Länge des Sounds (Anzahl der Samples)
Speichern / Abspielen von Sounds
‰
‰
saveSound(sound, filename) – abspeichern des Sounds als .wav Datei
playSound(sound) – bis jetzt nur Windows und Linux
„
Prof. B. Jung
andere Plattformen: Abspeichern des Sounds, Abspielen mit jeweiligem Audio-Player
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
TUBAF Sound: Beispiele für Sound-Funktionen
>>> from TUBAFSound import *
>>> filename = r'C:\Dokumente und Einstellungen\Jung\Eigene
Dateien\c4.wav'
>>> sound = makeSound(filename)
>>> print sound
Sound of length 55125
>>> getSample(sound, 0)
20
>>> getSample(sound, 55124)
4225
>>> samples = getSamples(sound)
>>> print samples[0:10] # ':' ist sog. 'slice'-operator
[20, 946, 1948, 2919, 3814, 4748, 5673, 6547, 7333, 8130]
>>> playSound(sound)
# nur Windows u. Linux
>>> saveSound(sound, 'c4-copy.wav') # alle Plattformen
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
6
Erinnerung: range() Funktion
>>> range(3)
[0, 1, 2]
>>> range(1, 3)
[1, 2]
>>> range(3, 1)
[]
>>> range(-1, 5)
[-1, 0, 1, 2, 3, 4]
>>> range(100)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … 99]
Oft Verwendung in Zählschleifen: for index in range(10): …
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Erinnerung: Bearbeitung von Listen mit Zählschleifen
„
Beispiel: Verdoppeln aller Listenelemente
>>> def verdopple( liste):
for index in range( len(liste) ):
wert = liste[index]
# Zugriff auf i. Element
liste[index] = wert * 2
# Zuweisung an i. Element
>>> liste = [10,11,12,13,14]
>>> verdopple(liste)
>>> liste
[20, 22, 24, 26, 28]
>>> liste = [10,11,12,13,14,15,16,17,18,19]
>>> verdopple(liste)
>>> liste
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38]
>>>
„
Sound-Bearbeitung = Manipulation von Arrays/Listen
‰
‰
analog zu obigem Beispiel
Listen allerdings länger, z.B. 22050 Elemente pro Sekunde des Sounds
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
7
TUBAF Sound: Einfaches Gerüst für Programme zur
Sound-Verarbeitung
Iteration über alle Samples mit for-Schleife !
Python-Skript
def manipulateSound(sound):
for index in range( getLength(sound) ):
value1 = getSample(sound, index)
value2 = value1
# oder sinnvolleren neuen Wert
setSample(sound, index, value2)
Benutzung
>>>
>>>
>>>
>>>
>>>
>>>
from TUBAFSound import *
filename = "techno_mono.wav"
sound = makeSound(file)
manipulateSound(sound)
playSound(sound)
Prof. B. Jung
# bzw. andere wav-Datei
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Beispiel: Lautstärke erhöhen
„
Amplitude des Sounds muss größer werden
‰
Æ alle Sample-Werte z.B. verdoppeln
alt:
neu:
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
118
38
-2
-222
-60
36
36
0
1
2
3
4
5
6
Python-Skript:
def increaseVolume(sound):
for index in range(getLength(sound)):
value = getSample(sound, index)
setSample(sound, index, value*2) >>>
>>>
>>>
>>>
>>>
Prof. B. Jung
Benutzung:
filename = "techno_mono.wav"
sound = makeSound(filename)
increaseVolume(sound)
playSound(sound)
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
8
Arbeitsweise von increaseVolume():
Start der Schleife
for Schleife setzt index = 0
„
def increaseVolume(sound):
for index in range(getLength(sound)):
sample = getSample(sound, index)
setSample(sound, index, sample*2)
59
19
-1
-111
-30
0
1
2
3
4
…
index
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Arbeitsweise von increaseVolume():
Ausführung des Blocks
„
„
sample erhält den Wert
des ersten Samples (d.h.
index 0) von sound
Wert des Samples an
index wird neu gesetzt
(bisheriger Wert mal 2)
def increaseVolume(sound):
for index in range(getLength(sound)):
sample = getSample(sound, index)
setSample(sound, index, sample*2)
sample
118
19
-1
-111
-30
0
1
2
3
4
…
index
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
9
Arbeitsweise von increaseVolume():
Das nächste Sample …
Kontrolle kehrt zum
Schleifenanfang zurück;
index wird nun
inkrementiert und erhält
somit den Wert 1
„
def increaseVolume(sound):
for index in range(getLength(sound)):
sample = getSample(sound, index)
setSample(sound, index, sample*2)
118
19
-1
-111
-30
0
1
2
3
4
…
index
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Arbeitsweise von increaseVolume():
… verdoppeln des nächsten Samples
def increaseVolume(sound):
„
„
nun wird Wert des
nun aktuellen
Samples (index = 1)
gelesen …
… und auf den
neuen Wert 38
gesetzt
for index in range(getLength(sound)):
sample = getSample(sound, index)
setSample(sound, index, sample*2)
sample
118
38
-1
-111
-30
0
1
2
3
4
…
index
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
10
Arbeitsweise von increaseVolume():
… und so weiter für alle Samples
„
„
def increaseVolume(sound):
Schleife iteriert über alle
Indices
somit sind alle SampleWerte nun verdoppelt
for index in range(getLength(sound)):
sample = getSample(sound, index)
setSample(sound, index, sample*2)
sample
118
38
-2
-222
-60
0
1
2
3
4
…
index
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Beispiel: Benutzung von increaseVolume()
>>>
>>>
>>>
>>>
>>>
>>>
sound = makeSound("techno_mono.wav")
playSound(sound)
increaseVolume(sound)
playSound(sound)
saveSound(sound, "techno_mono_louder.wav")
Zur Erinnerung:
Verdopplung Amplitude
≠ doppelte Lautstärke
(logarithm. Korrelation)
original
Amplitude * 2
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
11
Beispiel: Wiederholtes Erhöhen der Lautstärke
original
Amplitude * 2
Amplitude * 4
Clipping – Physikalische Schallwelle wird aufgrund der Beschränkung
auf 16 Bit pro Sample nicht adäquat repräsentiert Æ schlechte Klangqualität
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Test: Extremer Sound
„
„
„
„
Sound soll nur Samples mit extremen Sample-Werten enthalten:
Falls Sample-Wert im Original >= 0, dann neuer Wert = 32767
Andernfalls neuer Wert = -32768
Æ Verwendung von if … else
original
extrem
Prof. B. Jung
def toTheExtreme(sound):
for index in range(len(sound)):
value = getSample(sound, index)
if (value>=0):
setSample(sound, index, 32767)
else:
setSample(sound, index, -32768)
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
12
Normalisierung von Sound
„
„
Skalierung der Amplituden in einem Sound, so dass maximaler SampleWert = 32767 (und minimaler Sample-Wert = -32768)
Schritte:
‰
‰
1.) Maximalen Sample-Wert loudest in Sound ermitteln
2.) Ermittlung des Verstärkungsfaktors amp, so dass
„
„
‰
amp * loudest = 32767
d.h. amp = 32767/loudest
3.) Verstärkung aller Sample-Werte durch Multiplikation mit amp
original
normalisiert
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Normalisierung von Sound
def normalize(sound):
loudest = 0
for s in getSamples(sound):
loudest = max(loudest, s )
amp = 32767.0 / loudest
print "Groesster Sample-Wert in Original: ",
print "Verstaerkungsfaktor: ", amp
loudest
for index in range( len(sound) ):
value = getSample(sound, index)
louder = int(amp * value)
setSample(sound, index, louder)
>>> sound = makeSound("techno_mono.wav")
>>> normalize(sound)
Groesster Sample-Wert in Original: 14007
Verstaerkungsfaktor: 2.33933033483
>>> saveSound(sound,"techno_mono_normalized.wav")
>>>
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
13
Rückwärts-Sound
“[Revolution] number 9, number 9, number 9”
„
Rückwärts-Abspielen von Sound war zu Beatles-Zeiten beliebt …
„
Umsetzung mit digitalem Sound
‰
‰
siehe z.B. en.wikipedia.org zu "Revolution 9"
Sound-Array einfach umkehren:
vorwärts:
rückwärts:
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
18
18
-30
-111
-1
19
59
0
1
2
3
4
5
6
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Rückwärts-Listen
„
Vorgehen:
‰
‰
Zweite Liste listeRueckwaerts erzeugen, die Ergebnis enthalten soll
Verwendung von zwei Indices (Laufvariablen)
„
„
‰
indexRueck – läuft von 0, 1, 2, …, n-1, zum Durchlaufen von listeRueckwaerts
indexVor – läuft von n-1, n-2, …, 2, 1, 0, zum Durchlaufen der Originalliste
Bei jedem Schleifendurchlauf wird
„
„
„
indexRueck um 1 erhöht, durch range-Funktion
indexVor um 1 erniedrigt, per expliziter Zuweisung
ein Wert von Originalliste in neue Liste listeRueckwaerts kopiert
def rueckwaerts(liste):
listeRueckwaerts = [0] * len(liste)
indexVor = len(liste) - 1
for indexRueck in range( len(liste) ):
wert = liste[indexVor]
listeRueckwaerts[indexRueck] = wert
indexVor = indexVor - 1
return listeRueckwaerts
Am Ende der
Liste anfangen
indexVor läuft
rückwärts
Test:
>>> rueckwaerts([1,2,3])
>>> rueckwaerts([0,-1,88,7])
>>> rueckwaerts([])
[3,
Prof. B.2,
Jung1]
[7, 88,
-1,
0] WS 2007/08
Einführung
in die
Informatik,
[] TU Bergakademie Freiberg
14
Rückwärts-Sound
„
Vorgehen (analog zu Umkehrung von Listen):
‰
‰
Kopien des Original-Sounds erzeugen (sound Æ destSound)
Verwendung von zwei Indices (Laufvariablen)
„
„
‰
destIndex – läuft von 0, 1, 2, …, n-1
srcIndex – läuft von n-1, n-2, …, 2, 1, 0
Bei jedem Schleifendurchlauf wird
„
„
destIndex um 1 erhöht, durch range-Funktion
srcIndex um 1 erniedrigt, per expliziter Zuweisung
Am Ende des
Sounds anfangen
from TUBAFSound import *
def backwards(sound):
destSound = copySound(sound)
srcIndex = getLength(sound) - 1
for destIndex in range( getLength(sound) ):
sample = getSample(sound, srcIndex)
setSample(destSound, destIndex, sample)
srcIndex = srcIndex - 1
return destSound
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
srcIndex läuft
rückwärts
TU Bergakademie Freiberg
Rückwärts-Sound
“number 9, number 9, number 9”
“Turn me on, dead man” ???
def backwards(sound):
destSound = copySound(sound)
srcIndex = getLength(sound) - 1
for destIndex in range( getLength(sound) ):
sample = getSample(sound, srcIndex)
setSample(destSound, destIndex, sample)
srcIndex = srcIndex - 1
return destSound
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
15
Konkatenierung von Sound
„
Aneinanderhängen von Sounds in zwei Dateien zu Sound in einer
Datei
‰
Æ Aneinanderhängen von Sample-Arrays
59
19
-1
-111
0
1
2
3
+
-30
18
18
0
1
2
=
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Konkatenierung von Sound
„
Vorgehen zur Konkatenierung von zwei Sounds:
1.
Erzeuge neues, leeres Sound-Objekt, das mindestes so lang ist wie beide
Eingabe-Sounds zusammen
‰
2.
3.
TUBAF Sound: makeEmptySound(t) – t ist Länge des Sounds in Sekunden
Kopiere Sample-Werte von erstem Sound-Objekt an Anfang von neuem
Sound-Objekt
Kopiere Sample-Werte von zweitem Sound-Objekt in neues SoundObjekt, beginnend hinter den Samples des ersten Sounds
59
0
Prof. B. Jung
19
1
-1
2
+
=
-111
3
59
19
-1
-111
0
1
2
3
-30
0
18
1
18
2
-30
18
18
4
5
6
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
16
Konkatenierung von Sound
„
Neues Teilproblem:
‰
„
Berechnung der Dauer eines Sounds in Sekunden
Relevante Funktionen von TUBAFSound:
‰
‰
getLength(sound) – Anzahl Samples eines Sounds
getSamplingRate(sound)
„
z.B. 22050 oder 44100 Samples / Sekunde
Æ Dauer eines Sounds in Sekunden:
‰
‰
‰
‰
duration(sound)
in TUBAF-Sound enthalten
definiert als: getLength(sound) / getSamplingRate(sound)
Liefert i.d.R. float-Wert, z.B. 3.219
>>> snd = makeSound("techno_mono.wav")
>>> duration(snd)
3.8552380952380951
>>>
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
Konkatenierung von Sound
def concatSounds(sound1, sound2):
dur = duration(sound1) + duration(sound2)
print "Duration:", dur
sound = makeEmptySound( dur )
index = 0
for i in range(len(sound1)):
value = getSample(sound1,i)
setSample(sound, index, value)
index = index + 1
for i in range(len(sound2)):
value = getSample(sound2,i)
setSample(sound, index, value)
index = index + 1
return sound
>>> snd1 = makeSound("InformatikMachtSpass.wav")
>>> snd2 = makeSound("meistens.wav")
>>> snd3 = concatSounds(snd1,snd2)
Duration: 3.26063492063
>>> playSound(snd3)
>>>
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Länge des
konkatenierten
Sounds berechnen
(in Sekunden)
Leeren Sound
erzeugen
Alle Samples
von Sound1
kopieren
Alle Samples
von Sound2
kopieren
TU Bergakademie Freiberg
17
Kontext: Manipulation digitaler Medien
„
… ist einfach: nur Ersetzung von Bytes durch andere Bytes
„
z.B. Bilder
„
z.B. Sound
‰
‰
‰
www.br-online.de, 2005
echtes Zitat des Dozenten: "Informatik macht Spaß"
auch mal gesagt: "meistens"
nie gesagt: "Informatik macht Spaß … meistens"
„
Prof. B. Jung
selbst falls Sound-Dateien dieses Inhalts existieren sollten!
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Nachtrag: Sound-Bearbeitung mittels Builtin-Funktionen
von Python für Listen
„
Eingebaute Funktionen zur Manipulation von Listen in Python, u.a.:
‰
‰
‰
‰
sei liste = [1,2,3]
Liste rückwärts: liste.reverse() Æ [3,2,1]
Konkatenierung von Listen: liste+[4,5] Æ [1,2,3,4,5]
Erweitern um zweite Liste: liste.extend([2,1]) Æ [1,2,3,2,1]
damit sind vereinfachte Funktionen zur Sound-Manipulation möglich:
def backwards_usingBuiltIns(sound):
sound.getSamples().reverse()
return sound
def concatSounds_usingBuiltIns(sound1,sound2):
sound = makeEmptySound(0)
setSamples(sound, getSamples(sound1) + getSamples(sound2))
return sound
def concatSounds_usingBuiltIns2(sound1,sound2):
sound1.getSamples().extend(sound2.getSamples())
sound1
Prof.return
B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
18
Addition von Sound
„
Natürlich vorkommende Sounds sind oft
die Überlagerung mehrerer einfacherer
Sounds
„
Addition digitaler Sounds ist einfach:
‰
„
nur Sample-Werte addieren
Anwendungen
‰
Mixen von Sound
„
„
einfache Akkorde
Mischen von komplexer Sounds
‰
‰
‰
auch Übergänge (fade-in / fade-out) durch
Verändern der Lautstärke
Erzeugen von Echos
…
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Addieren von Sound
+
10
20
30
40
50
60
20
1
6
2
12
3
18
4
28
5
38
6
-15
7
-40
16
32
48
68
88
45
-20
0
1
2
3
4
5
6
def addSounds(sound1,sound2):
for index in range( getLength(sound1) ):
s1Sample = getSample(sound1,index)
s2Sample = getSample(sound2,index)
setSample(sound1,index,s1Sample+s2Sample)
return sound1
Kombinierter Sound in sound1
d.h. sound1 ist nach Funktionsaufruf verändert (sound2 bleibt wie zuvor)
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
19
Erzeugen von Akkorden durch Mischen von drei Sounds
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
c4=makeSound("bassoon-c4.wav")
e4=makeSound("bassoon-e4.wav")
g4=makeSound("bassoon-g4.wav")
playSound(c4)
addSounds(c4,e4)
playSound(c4)
addSounds(c4,g4)
playSound(c4)
bassoon (engl.): Fagott
oder auch:
>>>
>>>
>>>
>>>
>>>
c4=makeSound("bassoon-c4.wav")
e4=makeSound("bassoon-e4.wav")
g4=makeSound("bassoon-g4.wav")
playSound( addSounds( addSounds(c4,e4), g4) )
(c4+e4)
(c4+e4) + g4
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Akkord mit Delay
„
„
z.B. zweiter Sound mit Delay von 5000 Samples
z.B. dritter Sound mit Delay von 10000 Samples
def makeChord(sound1,sound2,sound3):
for index in range( getLength(sound1) ):
s1Sample = getSample(sound1,index)
if index > 5000:
sound1 wird
s2Sample=getSample(sound2,index-5000)
überschrieben
setSample(sound1,index,s1Sample+s2Sample)
if index > 10000:
s3Sample = getSample(sound3,index-10000)
setSample(sound1,index,s1Sample+s2Sample+s3Sample)
return sound1
>>> makeChord(c4,e4,g4)
<TUBAFSound.Sound instance at 0x00C454E0>
>>> playSound(c4)
>>>
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
20
Erzeugen von Echos
„
Idee: Neuer Sample-Wert erhält Anteile des bisherigen Samples + Anteile
des Samples, das delay Samples zurück liegt
‰
Zur Vermeidung, dass Amplitude über Maximalwert liegt (d.h. neuer SampleWert > 32767) fließen altes und Echo-Sample mit Faktoren < 1 in neuen Sound
ein
Beispiel: Delay 4 (realistisch: 10000-20000)
10
20
30
40
50
60
70
0
1
2
3
4
5
6
Faktor 0.6
Faktor 0.4
Prof. B. Jung
6
12
18
24+4
=28
30+8
=38
36+12
=48
42+16
=58
0
1
2
3
4
5
6
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Erzeugen von Echos
Python-Code
Kopie des Eingabe-Sounds
def echo(sound, delay):
destSound = copySound(sound)
for index in range(delay):
origSample = getSample(sound, index)
setSample(destSound,index,int(0.6*origSample))
for index in range(delay, getLength(sound)):
origSample = getSample(sound,index)
echoSample = getSample(sound,index-delay)
newSample = int(0.6*origSample+0.4*echoSample)
setSample(destSound,index,newSample)
return destSound
nur Kopie wird
verändert!
>>> snd = makeSound("InformatikMachtSpass.wav")
>>> playSound( echo(snd, 10000) )
>>> playSound( echo(snd, 20000) )
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
21
Synthetischer Sound
„
Z.B.
‰
Elektrische Orgeln, 1934
„
‰
Synthesizer, 1964 (Moog)
„
‰
Prinzip: Überlagerung mehrerer
Sinus-Wellen ("additive Synthese")
Hörbeispiel: "Popcorn", 1969; erster
nur mit Synthesizer eingespielter
Pop-Hit
Hammond-Orgel, wikipedia.org
MIDI, 1983
„
„
„
"Musical Instrument Digital Interface"
Befehle zur Ansteuerung von
digitalen Instrumenten bzw.
Soundkarten
(analog zu Vektorgrafik)
Hörbeispiel
Moog-Synthesizer
www.wendycarlos.com
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Innovation
1970er Jahre: "Wall of Synthesizers"
Foto: Emerson, Lake & Palmer, 1974
(Moog-Synthesizer)
Prof. B. Jung
Moderne Synthesizer
Foto: Kraftwerk,
www.kraftwerk.com
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
22
Synthetischer Sound
Generierung von Sinus-Wellen
„
Wie viele Zyklen pro Sekunde?
„
Wie viele Samples pro Zyklus?
‰
‰
‰
„
0
‰
2π
Frequenz = Anzahl der Zyklen pro Sekunde
Æ SamplesPerCycle = SamplingRate / Frequenz
z.B. 22050 / 440 = 50.11
Wert des i.-ten Samples (i = 1…22050):
‰
π
1 Zyklus
Bereich -1.0 ... +1.0: sin(i / SamplesPerCycle * 2 * pi)
Multiplikation mit max. Amplitude!
def sineWave(freq, amplitude = 4000):
'''Generate a 1 second sine wave sound'''
from math import pi, sin
buildSin = makeEmptySound(1) # make a 1 sec. empty sound
sr = getSamplingRate(buildSin)
# e.g. 22050
samplesPerCycle = float(sr) / freq # e.g. 22050 / 440 = 50.11
for pos in range( len(buildSin) ):
rawSample = sin( (pos / samplesPerCycle) * 2 * pi)
sampleVal = int( amplitude*rawSample)
setSample(buildSin, pos, sampleVal)
return buildSin
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Synthetischer Sound
Generierung von Rechteckwellen-Wellen
„
Rechteckwellen
„
Generierung
‰
‰
‰
(etwas) komplexerer Klang als Sinuswellen
falls Sinus > 0 :
Samplewert = Amplitude
sonst: Samplewert = -Amplitude
def squareWave(freq, amplitude = 4000):
'''Generate a 1 second square wave sound'''
from math import pi, sin
buildSquare = makeEmptySound(1)
# make a 1 sec. empty sound
sr = getSamplingRate(buildSquare)
# e.g. 22050
samplesPerCycle = float(sr) / freq
# e.g. 22050 / 440 = 50.11
for pos in range( len(buildSquare) ):
if sin( (pos / samplesPerCycle) * 2 * pi) >= 0:
sampleVal = amplitude
else:
sampleVal = - amplitude
setSample(buildSquare, pos, sampleVal)
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
return buildSquare
23
Synthetischer Sound – weitere Wellenformen
http://commons.wikimedia.org/wiki/Image:Waveforms.png
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Ändern der Frequenz von Sounds
„
Vorige Vorlesung: Ändern der Amplitude
von Sounds
‰
„
Amplitude (logarithmisch) korreliert mit Lautstärke
Jetzt: Ändern der Frequenz von Sounds
‰
‰
Frequenz (logarithmisch) korreliert mit Tonhöhe
Auswirkung auf Tonhöhe und Geschwindigkeit
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
24
Halbieren der Frequenz von Sounds:
Idee
„
Sample-Werte des Original-Sounds jeweils doppelt in Ziel-Sound
kopieren
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
59
59
19
19
-1
-1
-111
0
1
2
3
4
5
6
[Besser als doppeltes Kopieren wäre Interpolation der Sample-Werte]
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
Halbieren der Frequenz:
Python-Skript
TU Bergakademie Freiberg
Kopie des Sounds erzeugen
(und später bearbeiten)
def half(sound):
destSound = copySound(sound)
Konvertierung Float Æ Integer
z.B. 1.5 Æ 1
srcIndex = 0.0
for destIndex in range( getLength(destSound) ):
sample = getSample(sound, int(srcIndex) )
setSample(destSound, destIndex, sample)
srcIndex = srcIndex + 0.5
return destSound
>>>
>>>
>>>
>>>
>>>
Prof. B. Jung
Trace der Laufvariablen je Schleifendurchlauf:
destIndex: 0, 1, 2, 3, 4, 5, 6, 7, …
srcIndex: 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, …
int(srcIndex): 0, 0, 1, 1, 2, 2, 3, 3, 4, …
snd = makeSound("techno_mono.wav")
playSound(snd)
snd2 = half(snd)
playSound(snd2)
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
25
Verringern der Frequenz um beliebigen Faktor
Python-Skript (fast identisch mit vorigem Skript)
def slower(sound, rate):
"make the sound slower, rate should be at most 1.0"
destSound = copySound(sound)
srcIndex = 0.0
for destIndex in range( getLength(destSound) ):
sample = getSample(sound, int(srcIndex) )
setSample(destSound, destIndex, sample)
srcIndex = srcIndex + rate
return destSound
Trace der Laufvariablen je Schleifendurchlauf bei rate = 0.8:
destIndex: 0, 1, 2, 3, 4, 5, 6, 7, …
srcIndex: 0.0, 0.8, 1.6, 2.4, 3.2, 4.0, 4.8, 5.6, …
int(srcIndex): 0, 0, 1, 2, 3, 4, 4, 5, …
>>> snd = makeSound("techno_mono.wav")
>>> snd2 = slower(snd, 0.8)
>>> playSound(snd2)
Prof. B. Jung
TU Bergakademie Freiberg
Einführung in die Informatik, WS 2007/08
Verdoppeln der Frequenz von Sounds:
Idee
„
Nur jedes zweite Sample des Original-Sounds in Ziel-Sound
kopieren
‰
Falls Ziel-Sound (formal) gleiche Länge wie Original haben soll: zweite
Hälfte des Ziel-Sounds: z.B. mit Nullen füllen
Prof. B. Jung
59
19
-1
-111
-30
18
18
0
1
2
3
4
5
6
59
-1
-30
18
0
0
0
0
1
2
3
4
5
6
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
26
Verdoppeln der Frequenz:
Python-Skript
Trace der Laufvariablen je Schleifendurchlauf:
def double(sound):
sourceIndex: 0, 2, 4, 6, 8 …
destSound = copySound(sound)
destIndex: 0,1, 2, 3, 4, 5, …
destIndex = 0
for sourceIndex in range(0, len(sound), 2):
value = getSample(sound, sourceIndex)
setSample( destSound, destIndex, value)
destIndex = destIndex + 1
# Zero out the rest of the target sound -- it's only half full!
# Zeros are silent.
for secondHalf in range(len(destSound)/2, len( destSound)):
setSample(destSound, destIndex, 0)
destIndex = destIndex + 1
return destSound
>>> snd = makeSound("techno_mono.wav")
>>> snd2 = double(snd)
>>> playSound(snd2)
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Verdoppeln der Frequenz OHNE Auffüllen des
Ziel-Sounds mit Nullen
def doubleNoClear(sound):
destSound = copySound(sound)
destIndex = 0
for sourceIndex in range(0, getLength(sound), 2):
value = getSample(sound, sourceIndex)
setSample( destSound, destIndex, value)
destIndex = destIndex + 1
return destSound
>>> snd = makeSound("techno_mono.wav")
>>> snd2 = doubleNoClear(snd)
>>> playSound(snd2)
Æ 2. Hälfte des neuen Sounds wie Original-Sound
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
27
Beliebiges Verändern der Frequenz von Sounds
basiert auf slower-Skript
def changeFreq(sound, rate):
destSound = copySound(sound)
srcIndex = 0.0
for destIndex in range( len(destSound) ):
if srcIndex <= getLength(sound):
sample = getSample(sound, int(srcIndex) )
else: # possibly fill end of sound with zeros
sample = 0
wie slower-Skript,
aber mit Auffüllen
von Nullen,
falls notwendig
setSample(destSound, destIndex, sample)
srcIndex = srcIndex + rate
return destSound
>>> playSound( changeFreq(snd, 0.8) )
>>> playSound( changeFreq(snd, 1.3) )
Prof. B. Jung
# langsamer
# schneller
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
Singender Eisberg entdeckt
Ein Lied von Kälte und Einsamkeit
Eigentlich wollten Forscher des Bremerhavener Alfred-Wegener-Instituts für Polar- und
Meeresforschung seismische Signale in der Antarktis untersuchen. Als sie die Aufnahmen
auswerteten, entdeckten sie völlig unerwartet ein neues Talent: ein Eisberg, der
musikalisch anmutende Klänge erzeugt.
Mit einer Frequenz von 0,5 Hertz ist der von den Forschern als "harmonischer Tremor"
beschriebene Ton für das menschliche Ohr zwar nicht wahrnehmbar. Auf schnellerer
Geschwindigkeit abgespielt hört er sich jedoch an wie ein Bienenschwarm oder ein sich
warmspielendes Orchester, berichteten die Forscher. Redaktionsmitglieder von
tagesschau.de fühlten sich eher an die Geräuschkulisse eines Formel-1-Rennens oder
sogar an Celine Dions Lied "My Heart will go on" aus dem Film Titanic erinnert. …
www.tagesschau.de, 25.11.2005
eisberg.wav
Prof. B. Jung
Einführung in die Informatik, WS 2007/08
TU Bergakademie Freiberg
28

Documents pareils