(Version 2022_01_03)
In diesem Tutorial wird erläutert, wie man die Motivsuche verfeinern kann, um nicht nur nach Tonfolgen, sondern nach Tonfolgen mit einem bestimmten Rhythmus zu suchen.
Das Tutorial knüpft an das "Tutorial Noten Advanced Part 1: Motivsuche bei Josquin" an. Die ersten Schritte sind daher identisch. Wir wählen jedoch als Musikbeispiel eine Komposition eines Komponisten, bei dem der Umgang mit Motiven eine besonders große Rolle spielt: den ersten Satz des Streichquartett Op. 18, No. 1, von Ludwig van Beethoven.
from music21 import *
url = 'https://analyse.hfm-weimar.de/database/03/BeLuva_Op18_1-6_1-4_StringQuar_003_00104.xml'
music = converter.parse(url)
music.show()
Um nach Wiederholungen des Anfagsmotivs in exakt derselben rhythmischen Struktur zu suchen, muss nun das melodische Muster auch in rhythmischer Hinsicht definiert werden:
StreamMot=stream.Stream()
StreamMot.append(note.Note('F', quarterLength=1.5))
StreamMot.append(note.Note('G', quarterLength= 0.25))
StreamMot.append(note.Note('F', quarterLength=0.25))
StreamMot.append(note.Note('E', quarterLength=0.5))
StreamMot.append(note.Note('F', quarterLength=0.5))
# Der Zusatz 'quaterLength= ' bezieht sich auf Vielfache einer Viertelnote = 1.
StreamMot.show()
s = music.recurse().notes
# Die Suche wird nun mit dem Befehl 'search.noteNameRhythmicSearch' erstellt.
p = search.noteNameRhythmicSearch(s, StreamMot)
p
[75, 815, 821, 1933, 2847, 2853, 3202, 3735, 3741, 3908, 3914, 4011, 4017]
Wie erwartet, taucht das Motiv relativ häufig auf: genau 13 Mal!
print(len(p))
13
Und nun wie gehabt: Ermittlung der exakten Position in der Partitur (Takt, Zählzeit, Stimme):
zähler=1
for Position in p:
startingNote=s[Position]
startingMeasure = startingNote.measureNumber
startingBeat = startingNote.beat
startingPart = startingNote.getContextByClass('Part')
print('%2s %3s %3s' %(zähler, startingNote.nameWithOctave, startingMeasure), startingBeat, startingPart)
zähler+=1
1 F5 22 1.0 <music21.stream.Part Violin> 2 F5 179 1.0 <music21.stream.Part Violin> 3 F5 181 1.0 <music21.stream.Part Violin> 4 F4 181 1.0 <music21.stream.Part Violin> 5 F3 179 1.0 <music21.stream.Part Viola> 6 F3 181 1.0 <music21.stream.Part Viola> 7 F4 300 1.0 <music21.stream.Part Viola> 8 F2 179 1.0 <music21.stream.Part Violoncello> 9 F2 181 1.0 <music21.stream.Part Violoncello> 10 F3 262 1.0 <music21.stream.Part Violoncello> 11 F3 264 1.0 <music21.stream.Part Violoncello> 12 F2 302 1.0 <music21.stream.Part Violoncello> 13 F2 304 1.0 <music21.stream.Part Violoncello>
Markierung in der Partitur - wir nehmen die markante Stellung in T. 179-181, die gleich in mehreren Stimmen auftaucht:
for found in p:#Töne der Suchergebnisse markieren
for ffound in range(len(StreamMot)):
s[found+ffound].lyric = '*'
s[found+ffound].style.color='red'
music.measures(179,181).show()
Dummerweise hat Beethoven nun aber den Beginn des Motivs sehr oft nicht als punktierte Viertel, sondern meistens als übergebundene Viertel + Achtel notiert. Diese Schreibweise ist leider in den 13 Suchergebnissen nicht enthalten.
Um diese übergebundenen Noten zu berücksichtigen, muss in music21 ein Trick angewendet werden:
Der Befehl "stripTies" ersetzt zwei übergebundene Noten durch einen Ton dergleichen Länge. Durch diese Methode können nun die Motive mit übergebundenen Notenwerten ermittelt werden.
music_tie = converter.parse(url).stripTies(inPlace=True)
s1 = music_tie.recurse().notes
music_tie.show()
# Zeigt die Partitur ohne übergebundene Noten.
len(s)
# = Anzahl der Noten, wenn übergebundene Noten getrennt gezählt werden.
4049
len(s1)
# = Anzahl der Noten, ohne getrennte Zählung von übergebundenen Noten.
3917
Durch die Auflösung der Bindebögen gibt es also (4049-3917=) 132 weniger Noten!!
p1 = search.noteNameRhythmicSearch(s1, StreamMot)
Wenn wir die Motive vor und nach Löschung der Bindebögen auflisten, wird klar, das nun 22 Fälle hinzugekommen sind:
print('Ohne Zusammenführung übergebundener Noten:', len(p))
print('Mit Zusammenführung übergebundener Noten:', len(p1))
Ohne Zusammenführung übergebundener Noten: 0 Mit Zusammenführung übergebundener Noten: 35
Nun ermitteln wird die exakten Positonen der einzelnen Motive und markieren die Stellen in der Partitur:
zähler=1
for Position in p1:
startingNote=s1[Position]
startingMeasure = startingNote.measureNumber
startingBeat = startingNote.beat
startingPart = startingNote.getContextByClass('Part')
print('%2s %3s %3s' %(zähler, startingNote.nameWithOctave, startingMeasure), startingBeat, startingPart)
zähler+=1
1 F4 1 1.0 <music21.stream.Part Violin> 2 F4 3 1.0 <music21.stream.Part Violin> 3 F5 5 1.0 <music21.stream.Part Violin> 4 F4 9 1.0 <music21.stream.Part Violin> 5 F4 11 1.0 <music21.stream.Part Violin> 6 F5 13 1.0 <music21.stream.Part Violin> 7 F5 22 1.0 <music21.stream.Part Violin> 8 F5 159 1.0 <music21.stream.Part Violin> 9 F4 162 1.0 <music21.stream.Part Violin> 10 F5 179 1.0 <music21.stream.Part Violin> 11 F5 181 1.0 <music21.stream.Part Violin> 12 F5 183 1.0 <music21.stream.Part Violin> 13 F5 294 1.0 <music21.stream.Part Violin> 14 F4 1 1.0 <music21.stream.Part Violin> 15 F4 3 1.0 <music21.stream.Part Violin> 16 F4 9 1.0 <music21.stream.Part Violin> 17 F4 11 1.0 <music21.stream.Part Violin> 18 F4 181 1.0 <music21.stream.Part Violin> 19 F3 1 1.0 <music21.stream.Part Viola> 20 F3 3 1.0 <music21.stream.Part Viola> 21 F3 9 1.0 <music21.stream.Part Viola> 22 F3 11 1.0 <music21.stream.Part Viola> 23 F3 179 1.0 <music21.stream.Part Viola> 24 F3 181 1.0 <music21.stream.Part Viola> 25 F4 300 1.0 <music21.stream.Part Viola> 26 F3 1 1.0 <music21.stream.Part Violoncello> 27 F3 3 1.0 <music21.stream.Part Violoncello> 28 F3 9 1.0 <music21.stream.Part Violoncello> 29 F3 11 1.0 <music21.stream.Part Violoncello> 30 F2 179 1.0 <music21.stream.Part Violoncello> 31 F2 181 1.0 <music21.stream.Part Violoncello> 32 F3 262 1.0 <music21.stream.Part Violoncello> 33 F3 264 1.0 <music21.stream.Part Violoncello> 34 F2 302 1.0 <music21.stream.Part Violoncello> 35 F2 304 1.0 <music21.stream.Part Violoncello>
for found in p1:
for ffound in range(len(StreamMot)):
s1[found+ffound].lyric = '*'
s1[found+ffound].style.color='red'
music_tie.show()
In Music21 lässt sich ein Befehl programmieren, mit dem man auf einen Schlag nach chromatischen Transpositionen eines Motivs suchen kann. Zunächst benötigen wir folgenden Befehl:
def pitchClassEqual(n1, n2):
if not hasattr(n1, 'pitch'):
return False
if not hasattr(n2, 'pitch'):
return False
if n1.pitch.pitchClass == n2.pitch.pitchClass:
return True
else:
return False
Im Folgenden wird nach dem Motiv mit allen 12 chromatischen Anfangstonhöhen (und ihre jeweilige enharmonische Equivalenten) gesucht. Dafür muss man einen Algorithmus erstellen, der 12 Mal wiederholt wird. Ein zweiter Loop trägt dazu bei, die Informationen von jeder Wiederholung in die Ergebnisliste (results) einzutragen.
results = []
zähler = 1
# Die Ergebnisse müssen in einer extra Liste ("results") eingetragen werden.
# Der "zähler" vereinfacht das Aufzählen der Töne, wenn man diese nacheinander zeigen will.
for egal in range(12):#Suche 12 Mal
s_len = [StreamMot.notes[i].name for i in range (len(StreamMot.notes))]
print("------------\nSearching for:", *s_len, sep=' ')
p = search.streamSearchBase(s, StreamMot, algorithm=pitchClassEqual)
for notePosition in p:
startingNote=s[notePosition]
startingMeasure = startingNote.measureNumber
startingBeat = startingNote.beat
startingPart = startingNote.getContextByClass('Part')
results.append(notePosition)
print('%2s %3s %3s' %(zähler, startingNote.nameWithOctave, startingMeasure), startingBeat, startingPart.id)
zähler+=1
[n.transpose(1, inPlace=True) for n in StreamMot]
#Nach jeder Suche wird alles einen halben Ton nach oben transponiert
------------ Searching for: B- C B- A B- 1 B-5 131 1.0 Violin 2 B-5 152 2.0 Violin 3 B-4 207 1.0 Violin 4 B-4 283 2.0 Violin 5 B-4 292 1.0 Violin 6 B-4 123 1.0 Violin 7 B-4 131 2.0 Violin 8 B-4 187 2.0 Violin 9 B-3 207 1.0 Violin 10 B-4 286 1.0 Violin 11 B-3 119 1.0 Viola 12 B-3 121 1.0 Viola 13 B-4 130 1.0 Viola 14 B-2 119 1.0 Violoncello 15 B-2 121 1.0 Violoncello 16 B-3 129 1.0 Violoncello ------------ Searching for: B C# B B- B ------------ Searching for: C D C B C 17 C6 26 1.0 Violin 18 C5 301 1.0 Violin 19 C5 311 1.0 Violin 20 C4 21 2.0 Violin 21 C4 288 1.0 Violin 22 C4 290 1.0 Violin 23 C3 289 1.0 Viola 24 C3 291 1.0 Viola 25 C3 30 1.0 Violoncello 26 C3 32 1.0 Violoncello 27 C3 34 1.0 Violoncello 28 C3 36 1.0 Violoncello 29 C3 101 1.0 Violoncello 30 C3 103 1.0 Violoncello 31 C2 104 1.0 Violoncello 32 C3 105 1.75 Violoncello 33 C3 105 2.75 Violoncello 34 C2 106 1.0 Violoncello 35 C3 107 1.75 Violoncello 36 C3 107 2.75 Violoncello 37 C4 233 1.0 Violoncello 38 C4 235 1.0 Violoncello 39 C4 237 1.0 Violoncello ------------ Searching for: C# E- C# C C# 40 D-6 151 2.0 Violin 41 D-5 154 2.0 Violin 42 D-5 156 2.0 Violin 43 D-5 163 2.0 Violin 44 D-3 198 1.0 Viola 45 D-3 200 1.0 Viola 46 D-3 202 1.0 Viola 47 D-3 204 1.0 Viola 48 D-3 206 1.0 Viola ------------ Searching for: D E D C# D 49 D5 126 1.0 Violin ------------ Searching for: E- F E- D E- 50 E-6 137 1.0 Violin 51 E-5 135 2.0 Violin 52 E-3 41 1.0 Viola 53 E-3 43 1.0 Viola 54 E-3 45 1.0 Viola 55 E-4 137 2.0 Viola ------------ Searching for: E F# E E- E ------------ Searching for: F G F E F 56 F4 1 2.0 Violin 57 F4 3 2.0 Violin 58 F5 5 2.0 Violin 59 F4 9 2.0 Violin 60 F4 11 2.0 Violin 61 F5 13 2.0 Violin 62 F5 19 1.0 Violin 63 F5 22 1.0 Violin 64 F5 159 2.0 Violin 65 F4 162 2.0 Violin 66 F5 179 1.0 Violin 67 F5 181 1.0 Violin 68 F5 183 2.0 Violin 69 F5 282 1.0 Violin 70 F5 294 2.0 Violin 71 F4 312 1.0 Violin 72 F4 1 2.0 Violin 73 F4 3 2.0 Violin 74 F4 9 2.0 Violin 75 F4 11 2.0 Violin 76 F4 181 1.0 Violin 77 F4 287 1.0 Violin 78 F5 308 3.5 Violin 79 F3 1 2.0 Viola 80 F3 3 2.0 Viola 81 F3 9 2.0 Viola 82 F3 11 2.0 Viola 83 F3 179 1.0 Viola 84 F3 181 1.0 Viola 85 F4 300 1.0 Viola 86 F3 1 2.0 Violoncello 87 F3 3 2.0 Violoncello 88 F3 9 2.0 Violoncello 89 F3 11 2.0 Violoncello 90 F2 179 1.0 Violoncello 91 F2 181 1.0 Violoncello 92 F3 262 1.0 Violoncello 93 F3 264 1.0 Violoncello 94 F2 265 1.0 Violoncello 95 F3 266 1.75 Violoncello 96 F3 266 2.75 Violoncello 97 F2 267 1.0 Violoncello 98 F3 268 1.75 Violoncello 99 F3 268 2.75 Violoncello 100 F2 302 1.0 Violoncello 101 F2 304 1.0 Violoncello ------------ Searching for: F# G# F# F F# 102 G-5 155 2.0 Violin ------------ Searching for: G A G F# G 103 G5 15 2.0 Violin 104 G5 24 1.0 Violin 105 G4 284 1.0 Violin 106 G4 25 2.0 Violin 107 G3 285 1.0 Viola 108 G4 72 1.0 Violoncello 109 G4 74 1.0 Violoncello 110 G4 76 1.0 Violoncello ------------ Searching for: G# B- G# G G# 111 A-5 143 1.0 Violin 112 A-4 161 2.0 Violin 113 A-4 143 2.0 Violin 114 A-4 164 2.0 Violin 115 A-4 141 1.0 Viola 116 A-3 142 1.0 Violoncello ------------ Searching for: A B A G# A
print(len(results))
116
Damit haben wir beachtliche 116 Vorkommen des Motivs auf verschiedenen Tonstufen gefunden.
Suchen Sie in Notendateien Ihrer Wahl nach Motiven, die Sie dort vermuten, und nach deren Transpositionen! Zum Beispiel in Sonatensätzen nach markanten Motiven aus dem ersten oder zweiten Thema.