Kapitel 10: Signalverarbeitung mit Python: Sound · Multimedia Dateien Repräsentation von...

28
1 Kapitel 10: Signalverarbeitung mit Python: Sound Einführung in die Informatik Wintersemester 2007/08 Prof. Bernhard Jung Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg Übersicht 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 Signalverarbeitung mit Python: Sound

Transcript of Kapitel 10: Signalverarbeitung mit Python: Sound · Multimedia Dateien Repräsentation von...

1

Kapitel 10:

Signalverarbeitung mit Python: Sound

Einführung in die InformatikWintersemester 2007/08

Prof. Bernhard Jung

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Übersicht

Repräsentation von SoundAlgorithmen:

Erhöhen der LautstärkeNormalisierung von SoundRückwärts-SoundKonkatenierung von Sound

Kombination von SoundsAkkordeEcho

Synthetischer SoundFrequenz 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

Signalverarbeitung mit Python: Sound

2

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Akustik – die Lehre vom Schall

Schallwellen sind zyklischFrequenz einer Welle

Anzahl der Zyklen pro Sekundegemessen in Hertz(1 Hz = 1 Zyklus / Sekunde)

Amplitudemaximale Höhe der Welle

Natürlich vorkommende Klänge bestehen aus Überlagerung einer Vielzahl von Schallwellen

Amplitude

1 Zyklus

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Psychoakustik – Wahrnehmung von SchallLautstärke und Tonhöhe

Wahrgenommene Lautstärke korreliert (logarithmisch) mit AmplitudeVerdopplung der Amplitude ca. 3 Dezibel lauterDezibel: Maß für wahrgenommene Lautstärke

0 dB: Schwellwert für Wahrnehmbarkeit von Geräuschen60 dB: Unterhaltungsgespräch80 dB: Schreien

Wahrgenommene Tonhöhe korreliert (logarithmisch) mit FrequenzHöhere Frequenz größere TonhöheVerdopplung der Frequenz 1 Oktave höherMenschliches Gehör: 5 Hz – 20.000 Hz

3

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Digitalisierung von Sound

Sound Samplenumerische Repräsentation der Amplitude zu einem bestimmten Zeitpunkt(Messung des Drucks, den Sound-Welle an Mikrofonmembran erzeugt)

Beschreibung der Sound-Welle durch hinreichende Anzahl von Samples

AD-Wandler (Analog-Digital)

wie viele Samples notwendig?

PCM – Pulse Code Modulation:Digitale Repräsentation eines analogenSignals, bei welcher das Signal in uniformenIntervallen abgetastet wird und die Signal-größe in digitaler Form quantisiert wird

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Theorem von Nyquist

Theorem von Nyquist (bezogen auf Sound):

Sampling Rate: Anzahl der erfassten Samples pro Sekundez.B. Menschliche Stimmen: maximale Frequenz 4000 Hz

8000 Samples pro Sekunde notwendig (Telefon)z.B. Menschliches Gehör: maximale Frequenz ca. 22000 Hz

ca. 44000 Samples pro Sekunde notwendigCD-Qualität: 44.100 Samples / Sekunde3-Minuten Song benötigt 158.760.000 Samples (Stereo × 2)

Zur Repräsentation (und späteren Wiedergabe) von Sound mit maximaler Frequenz n Hertz

müssen mindestens 2n Samples abgenommen werden

4

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Typischerweise jeder Sample-Wert wird durch 2 Byte repräsentiert2 Byte = 16 Bitd.h. 216 = 65.536 verschiedene Zahlen darstellbar

Sample-Werte: -32.768 … 32.767Bem: Viele Varianten möglich, z.B. 8 Bit pro Sample

Digitaler Sound = Feld (Array) von Sound-SamplesAchtung: Komprimierte Speicherung in üblichen Datei-Formaten (z.B. mp3)

Digitale Soundverarbeitung = Manipulation von FeldernÄndern der Sample-WerteÄndern der Feldgröße

Digitaler Sound: Repräsentation von Sound in Computern

59 -111-119 -30 18 18

0 321 4 5 6

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Teil von Microsofts RIFF-Spezifikation für Multimedia DateienRepräsentation von Samplewerten und Formatinformationen größtenteils als "littleendian"z.B. Bytefolge24 17 1e 13repräsentiertHex-Zahl 0x131e1724= 320739108Falls 16 Bits per Sample, werden Samplewerte vorzeichenbehaftet (im Zweierkomplement) gespeichert, d.h. Wertebereich-32768 … 32767

WAVE-Dateiformat

Quelle: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/

5

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

WAVE-Dateiformat / Beispiel

0x00000824 = 2084

0x5622 = 22050

Mono = 1, Stereo =2

0x0d1ace11= 219860497

Quelle: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

TUBAFSound.pyFunktionen für die Sound-Verarbeitung

Skript mit Funktionen zur einfachen Verarbeitung von digitalem SoundEinschränkungen an Sound-Dateien

.wav Format16 Bit Sample-Breitemono (laden von Stereo ok)bevorzugte Samplingrate 22050

funktioniert aber auch mitanderen Samplingrates

VerwendungSkript auf Kurs-WebseiteSpeichern im Arbeitsverzeichnis

mit eigenen SkriptenSound-Dateien

Abspielen von Sound nur auf Windows u. Linuxalle Plattformen: Bearbeiteten Sound speichern, dann mit geeignetem Playerabspielen

>>> from TUBAFSound import *>>> sound = makeSound('c4.wav')>>> playSound(sound)>>> saveSound(sound,'c4-copy.wav')

6

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

TUBAF Sound: Funktionen für die Sound-Verarbeitung(Auswahl)

Öffnen von Sound-Dateien makeSound(dateiname) – Erzeugt internes Sound-Objekt

nur .wav Dateien !

Lesen und Setzen von Sample-WertengetSamples(sound) – liefert Liste aller SamplewertesetSamples(sound, samples) – setzt die Samplewerte getSample(sound, index) – liefert Wert eines Samples (als Integer-Zahl)setSample(sound, index, value) – setzt Wert eines SamplesgetLength(sound) bzw len(sound) – liefert Länge des Sounds (Anzahl der Samples)

Speichern / Abspielen von SoundssaveSound(sound, filename) – abspeichern des Sounds als .wav DateiplaySound(sound) – bis jetzt nur Windows und Linux

andere Plattformen: Abspeichern des Sounds, Abspielen mit jeweiligem Audio-Player

Prof. B. Jung 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\EigeneDateien\c4.wav' >>> sound = makeSound(filename)>>> print soundSound 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

7

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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. Elementliste[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/Listenanalog zu obigem BeispielListen allerdings länger, z.B. 22050 Elemente pro Sekunde des Sounds

8

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

TUBAF Sound: Einfaches Gerüst für Programme zur Sound-Verarbeitung

def manipulateSound(sound):for index in range( getLength(sound) ):

value1 = getSample(sound, index)value2 = value1 # oder sinnvolleren neuen WertsetSample(sound, index, value2)

>>> from TUBAFSound import *>>> filename = "techno_mono.wav" # bzw. andere wav-Datei>>> sound = makeSound(file)>>> manipulateSound(sound)>>> playSound(sound)>>>

Iteration über alle Samples mit for-Schleife !

Benutzung

Python-Skript

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

def increaseVolume(sound):for index in range(getLength(sound)):

value = getSample(sound, index)setSample(sound, index, value*2)

Beispiel: Lautstärke erhöhen

Amplitude des Sounds muss größer werdenalle Sample-Werte z.B. verdoppeln

59 -111-119 -30 18 18

118 -222-238 -60 36 36

alt:

neu:

>>> filename = "techno_mono.wav">>> sound = makeSound(filename)>>> increaseVolume(sound)>>> playSound(sound)>>>

Python-Skript:

Benutzung:

0 321 4 5 6

0 321 4 5 6

9

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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 -111-119 -30

0 321 4…

index

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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)

118 -111-119 -30

0 321 4…

sample

index

10

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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 -111-119 -30

0 321 4…

index

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Arbeitsweise von increaseVolume():… verdoppeln des nächsten Samples

nun wird Wert des nun aktuellen Samples (index = 1) gelesen …… und auf den neuen Wert 38 gesetzt

def increaseVolume(sound):

for index in range(getLength(sound)):

sample = getSample(sound, index)

setSample(sound, index, sample*2)

118 -111-138 -30

0 321 4…

sample

index

11

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Arbeitsweise von increaseVolume():… und so weiter für alle Samples

Schleife iteriert über alle Indicessomit sind alle Sample-Werte nun verdoppelt

def increaseVolume(sound):

for index in range(getLength(sound)):

sample = getSample(sound, index)

setSample(sound, index, sample*2)

118 -222-238 -60

0 321 4…

sample

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")>>>

original

Amplitude * 2

Zur Erinnerung: Verdopplung Amplitude≠ doppelte Lautstärke(logarithm. Korrelation)

12

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Beispiel: Wiederholtes Erhöhen der Lautstärke

original

Amplitude * 2

Amplitude * 4

Clipping – Physikalische Schallwelle wird aufgrund der Beschränkungauf 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 = 32767Andernfalls neuer Wert = -32768

Verwendung von if … else

original

extrem

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)

13

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Normalisierung von Sound

Skalierung der Amplituden in einem Sound, so dass maximaler Sample-Wert = 32767 (und minimaler Sample-Wert = -32768)Schritte:

1.) Maximalen Sample-Wert loudest in Sound ermitteln2.) Ermittlung des Verstärkungsfaktors amp, so dass

amp * loudest = 32767d.h. amp = 32767/loudest

3.) Verstärkung aller Sample-Werte durch Multiplikation mit amp

original

normalisiert

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Normalisierung von Sounddef normalize(sound):

loudest = 0for s in getSamples(sound):

loudest = max(loudest, s ) amp = 32767.0 / loudest

print "Groesster Sample-Wert in Original: ", loudestprint "Verstaerkungsfaktor: ", amp

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: 14007Verstaerkungsfaktor: 2.33933033483>>> saveSound(sound,"techno_mono_normalized.wav")>>>

14

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Rückwärts-Sound

Rückwärts-Abspielen von Sound war zu Beatles-Zeiten beliebt …siehe z.B. en.wikipedia.org zu "Revolution 9"

Umsetzung mit digitalem SoundSound-Array einfach umkehren:

“[Revolution] number 9, number 9, number 9”

59 -111-119 -30 18 18

18 -111-3018 -1 19 59

vorwärts:

rückwärts:

0 321 4 5 6

0 321 4 5 6

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Rückwärts-Listen

Vorgehen:Zweite Liste listeRueckwaerts erzeugen, die Ergebnis enthalten sollVerwendung von zwei Indices (Laufvariablen)

indexRueck – läuft von 0, 1, 2, …, n-1, zum Durchlaufen von listeRueckwaertsindexVor – läuft von n-1, n-2, …, 2, 1, 0, zum Durchlaufen der Originalliste

Bei jedem Schleifendurchlauf wirdindexRueck um 1 erhöht, durch range-FunktionindexVor um 1 erniedrigt, per expliziter Zuweisungein Wert von Originalliste in neue Liste listeRueckwaerts kopiert

def rueckwaerts(liste):listeRueckwaerts = [0] * len(liste)indexVor = len(liste) - 1for indexRueck in range( len(liste) ):

wert = liste[indexVor]listeRueckwaerts[indexRueck] = wertindexVor = indexVor - 1

return listeRueckwaerts

Am Ende derListe anfangen

indexVor läuftrückwärts

>>> rueckwaerts([1,2,3])

[3, 2, 1]

Test:>>> rueckwaerts([0,-1,88,7])

[7, 88, -1, 0]

>>> rueckwaerts([])

[]

15

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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-1srcIndex – läuft von n-1, n-2, …, 2, 1, 0

Bei jedem Schleifendurchlauf wirddestIndex um 1 erhöht, durch range-FunktionsrcIndex um 1 erniedrigt, per expliziter Zuweisung

from TUBAFSound import *

def backwards(sound):destSound = copySound(sound)srcIndex = getLength(sound) - 1for destIndex in range( getLength(sound) ):

sample = getSample(sound, srcIndex)setSample(destSound, destIndex, sample)srcIndex = srcIndex - 1

return destSound

Am Ende des Sounds anfangen

srcIndex läuftrückwärts

Prof. B. Jung Einführung in die Informatik, WS 2007/08 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) - 1for destIndex in range( getLength(sound) ):

sample = getSample(sound, srcIndex)setSample(destSound, destIndex, sample)srcIndex = srcIndex - 1

return destSound

16

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Konkatenierung von Sound

Aneinanderhängen von Sounds in zwei Dateien zu Sound in einer Datei

Aneinanderhängen von Sample-Arrays

59 -111-119 -30 18 18

59 -111-119

0 321

-30 1818

0 21

+

=

0 321 4 5 6

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Konkatenierung von Sound

Vorgehen zur Konkatenierung von zwei Sounds:1. Erzeuge neues, leeres Sound-Objekt, das mindestes so lang ist wie beide

Eingabe-Sounds zusammenTUBAF Sound: makeEmptySound(t) – t ist Länge des Sounds in Sekunden

2. Kopiere Sample-Werte von erstem Sound-Objekt an Anfang von neuem Sound-Objekt

3. Kopiere Sample-Werte von zweitem Sound-Objekt in neues Sound-Objekt, beginnend hinter den Samples des ersten Sounds

59 -111-119 -30 18 18

59 -111-1190 321

-30 18180 21+

=0 321 4 5 6

17

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Konkatenierung von Sound

Neues Teilproblem: Berechnung der Dauer eines Sounds in Sekunden

Relevante Funktionen von TUBAFSound:getLength(sound) – Anzahl Samples eines SoundsgetSamplingRate(sound)

z.B. 22050 oder 44100 Samples / Sekunde

Dauer eines Sounds in Sekunden:duration(sound)in TUBAF-Sound enthaltendefiniert 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 TU Bergakademie Freiberg

Konkatenierung von Sound

def concatSounds(sound1, sound2):dur = duration(sound1) + duration(sound2) print "Duration:", dursound = makeEmptySound( dur )index = 0for 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)>>>

Länge des konkateniertenSounds berechnen(in Sekunden)

Leeren Sounderzeugen

Alle Samples von Sound1kopieren

Alle Samples von Sound2kopieren

18

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Kontext: Manipulation digitaler Medien

… ist einfach: nur Ersetzung von Bytes durch andere Bytes

z.B. Bilder

z.B. Soundechtes Zitat des Dozenten: "Informatik macht Spaß"auch mal gesagt: "meistens"nie gesagt: "Informatik macht Spaß … meistens"

selbst falls Sound-Dateien dieses Inhalts existieren sollten!

www.br-online.de, 2005

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Nachtrag: Sound-Bearbeitung mittels Builtin-Funktionenvon 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]

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())return sound1

damit sind vereinfachte Funktionen zur Sound-Manipulation möglich:

19

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Addition von Sound

Natürlich vorkommende Sounds sind oft die Überlagerung mehrerer einfacherer Sounds

Addition digitaler Sounds ist einfach: nur Sample-Werte addieren

AnwendungenMixen von Sound

einfache AkkordeMischen von komplexer Sounds

auch Übergänge (fade-in / fade-out) durch Verändern der Lautstärke

Erzeugen von Echos…

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Addieren von Sound

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 sound1d.h. sound1 ist nach Funktionsaufruf verändert (sound2 bleibt wie zuvor)

10 403020 50 60 20

1 432 5 6 76 281812 38 -15 -40

16 684832 88 45 -20

0 321 4 5 6

+

20

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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

>>> 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

oder auch:

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 Samplesz.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:

s2Sample=getSample(sound2,index-5000)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)>>>

sound1 wirdüberschrieben

21

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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 Sample-Wert > 32767) fließen altes und Echo-Sample mit Faktoren < 1 in neuen Sound ein

10 403020 50 60 70

0 321 4 5 6

624+4=28

181230+8=38

36+12=48

42+16=58

0 321 4 5 6

Faktor 0.6Faktor 0.4

Beispiel: Delay 4 (realistisch: 10000-20000)

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Erzeugen von EchosPython-Code

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

>>> snd = makeSound("InformatikMachtSpass.wav")>>> playSound( echo(snd, 10000) ) >>> playSound( echo(snd, 20000) )

Kopie des Eingabe-Sounds

nur Kopie wird verändert!

22

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Synthetischer Sound

Z.B.Elektrische Orgeln, 1934

Prinzip: Überlagerung mehrerer Sinus-Wellen ("additive Synthese")

Synthesizer, 1964 (Moog)Hörbeispiel: "Popcorn", 1969; erster nur mit Synthesizer eingespielter Pop-Hit

MIDI, 1983"Musical Instrument Digital Interface"Befehle zur Ansteuerung von digitalen Instrumenten bzw. Soundkarten(analog zu Vektorgrafik) Hörbeispiel

Hammond-Orgel, wikipedia.org

Moog-Synthesizerwww.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)

Moderne SynthesizerFoto: Kraftwerk, www.kraftwerk.com

23

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Synthetischer SoundGenerierung von Sinus-Wellen

Wie viele Zyklen pro Sekunde? Frequenz = Anzahl der Zyklen pro Sekunde

Wie viele Samples pro Zyklus?SamplesPerCycle = SamplingRate / Frequenz

z.B. 22050 / 440 = 50.11Wert des i.-ten Samples (i = 1…22050):

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, sinbuildSin = makeEmptySound(1) # make a 1 sec. empty soundsr = getSamplingRate(buildSin) # e.g. 22050samplesPerCycle = float(sr) / freq # e.g. 22050 / 440 = 50.11for pos in range( len(buildSin) ):

rawSample = sin( (pos / samplesPerCycle) * 2 * pi)sampleVal = int( amplitude*rawSample)setSample(buildSin, pos, sampleVal)

return buildSin

π 2π0

1 Zyklus

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Synthetischer SoundGenerierung von Rechteckwellen-Wellen

Rechteckwellen(etwas) komplexerer Klang als Sinuswellen

Generierungfalls Sinus > 0 :Samplewert = Amplitudesonst: Samplewert = -Amplitude

def squareWave(freq, amplitude = 4000):'''Generate a 1 second square wave sound'''from math import pi, sinbuildSquare = makeEmptySound(1) # make a 1 sec. empty soundsr = getSamplingRate(buildSquare) # e.g. 22050samplesPerCycle = float(sr) / freq # e.g. 22050 / 440 = 50.11for pos in range( len(buildSquare) ):

if sin( (pos / samplesPerCycle) * 2 * pi) >= 0:sampleVal = amplitude

else:sampleVal = - amplitude

setSample(buildSquare, pos, sampleVal)return buildSquare

24

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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 SoundsFrequenz (logarithmisch) korreliert mit TonhöheAuswirkung auf Tonhöhe und Geschwindigkeit

25

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Halbieren der Frequenz von Sounds:Idee

Sample-Werte des Original-Sounds jeweils doppelt in Ziel-Sound kopieren

59 -111-119 -30 18 18

59 191959 -1 -1 -111

0 321 4 5 6

[Besser als doppeltes Kopieren wäre Interpolation der Sample-Werte]

0 321 4 5 6

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Halbieren der Frequenz:Python-Skript

def half(sound):destSound = copySound(sound)

srcIndex = 0.0for destIndex in range( getLength(destSound) ):

sample = getSample(sound, int(srcIndex) )setSample(destSound, destIndex, sample)srcIndex = srcIndex + 0.5

return destSound

>>> snd = makeSound("techno_mono.wav")>>> playSound(snd) >>> snd2 = half(snd)>>> playSound(snd2)>>>

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, …

Konvertierung Float Integerz.B. 1.5 1

Kopie des Sounds erzeugen (und später bearbeiten)

26

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Verringern der Frequenz um beliebigen FaktorPython-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.0for destIndex in range( getLength(destSound) ):

sample = getSample(sound, int(srcIndex) )setSample(destSound, destIndex, sample)srcIndex = srcIndex + rate

return destSound

>>> snd = makeSound("techno_mono.wav")>>> snd2 = slower(snd, 0.8) >>> playSound(snd2)

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, …

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

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

59 -111-119 -30 18 18

59 18-30-1

0 321 4 5 6

0 0 0

0 321 4 5 6

27

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Verdoppeln der Frequenz:Python-Skript

def double(sound):destSound = copySound(sound)destIndex = 0for 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)

Trace der Laufvariablen je Schleifendurchlauf:sourceIndex: 0, 2, 4, 6, 8 …destIndex: 0,1, 2, 3, 4, 5, …

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 = 0for 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

28

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Beliebiges Verändern der Frequenz von Soundsbasiert auf slower-Skript

def changeFreq(sound, rate):destSound = copySound(sound)

srcIndex = 0.0for destIndex in range( len(destSound) ):

if srcIndex <= getLength(sound):sample = getSample(sound, int(srcIndex) )

else: # possibly fill end of sound with zerossample = 0

setSample(destSound, destIndex, sample)srcIndex = srcIndex + rate

return destSound

>>> playSound( changeFreq(snd, 0.8) ) # langsamer>>> playSound( changeFreq(snd, 1.3) ) # schneller

wie slower-Skript, aber mit Auffüllen von Nullen, falls notwendig

Prof. B. Jung Einführung in die Informatik, WS 2007/08 TU Bergakademie Freiberg

Singender Eisberg entdeckt

Ein Lied von Kälte und EinsamkeitEigentlich 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