Entwicklung eines Algorithmus zur Generierung optimaler Tonsätze

Hochschule für Technik, Wirtschaft und Kultur Leipzig
Fakultät Informatik, Mathematik und Naturwissenschaften
Masterstudiengang Medieninformatik
Schriftliche Ausarbeitung zum Masterprojekt
Entwicklung eines Algorithmus zur
Generierung optimaler Tonsätze zu
Akkordsymbol-Folgen
Eingereicht von: Martin Finke
Matrikelnummer: 61931
Leipzig, 30. März 2015
Betreuer: Prof. Dr. rer. nat. Johannes Waldmann
Abstrakt
Im harmonischen Tonsystem westlicher Musik werden Akkorde oft als Akkordsymbole dargestellt. Beim Spielen auf einem Instrument entscheiden Musiker, wie die
zu spielenden Töne angeordnet werden. Diese Arbeit zeigt einen Algorithmus, der
zu jedem Akkordsymbol eines Songs eine optimale Anordnung der Töne findet.
Dafür werden Bewertungsregeln und Constraints verwendet, die den Bedürfnissen und Fähigkeiten des Musikers angepasst werden, zum Beispiel der Reichweite
seiner Hände. Jeder Akkord wird einzeln sowie im Zusammenhang mit seinem Vorgänger und Nachfolger bewertet. Das Problem wird als kürzeste-Wege-Problem in
einem Graphen modelliert, die Laufzeit ist polynomial. Eine Implementation in
der Programmiersprache Haskell mit Bewertungsfunktionen für das Klavier ist
vorhanden.
i
Abstract
In tonality of Western music, chords are commonly represented as chord symbols.
Musicians playing an instrument arrange the notes to be played for a given chord
symbol. This paper shows an algorithm that finds an optimal arrangement of notes
for each chord symbol in a song. It uses rating rules and constraints that can be
customized to fit the user’s requirements and capabilities, like the reaching area
of his hands. Each chord is rated in isolation and in the context of its ancestor
and successor. The problem is modeled as a shortest path problem in a graph
and solved in polynomial time. An implementation in the Haskell programming
language is provided, including rating functions for the piano.
ii
Inhaltsverzeichnis
1 Einleitung
1.1 Grundbegriffe . . . . .
1.2 Motivation . . . . . . .
1.3 Zielsetzung . . . . . .
1.4 Vorhandene Lösungen
1.5 Lösungsplan . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 Beschreibung des Algorithmus
2.1 Datenmodell . . . . . . . . . . . . .
2.2 Vorgehensweise . . . . . . . . . . .
2.3 Erzeugung möglicher Hände . . . .
2.4 Erzeugung möglicher Sub-Folgen .
2.5 Verbindung der Sub-Folgen . . . .
2.6 Finden einer optimalen Hand-Folge
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
3
3
.
.
.
.
.
.
4
4
8
9
12
13
15
3 Ergebnisse
17
4 Ausblick
21
Literatur
I
iii
1 Einleitung
1.1 Grundbegriffe
Ein Akkord ist das das gleichzeitige Erklingen von zwei oder mehr Noten [Kár65,
S. 63]. Akkorde sind eine der Grundlagen des harmonischen Tonsystems westlicher Musik [Deb07, S. 45] und spielen besonders in der Jazz- und Popmusik eine
zentrale Rolle. In diesen Musikrichtungen ist es üblich, Akkorde nicht als Noten
darzustellen, sondern als Akkordsymbol. Dieses gibt an, welche Tonart und welches
Tongeschlecht ein Akkord hat (zum Beispiel C-Dur). Es kann außerdem Angaben
über Töne enthalten, die zusätzlich zu Grundton, Quinte und der Terz des Tongeschlechts gespielt werden sollen. Diese zusätzlichen Töne heißen Spannungstöne.
Ein Akkordsymbol kann explizit angeben, welcher Ton beim Spielen der tiefste sein
muss (Slash-Akkord), enthält aber darüber hinaus keine Festlegung über die Anordnung der Töne im Notensystem. Außerdem ist nicht festgelegt, welcher Finger
welchen Ton spielt.
1.2 Motivation
Musiker, die Akkordinstrumente wie Gitarre oder Klavier spielen, setzen Akkordsymbole in gespielte Töne auf dem Instrument um. Dabei entscheiden sie über
die Anordnung der Töne und über den Fingersatz. Eine Akkordlage ist eine mögliche Anordnung der Töne eines Akkordsymbols. Besonders im Jazz wird dieser
Schritt häufig improvisiert, während das Lied gespielt wird. Der Grund ist, dass
Lieder spontan während einer Jam-Session ausgewählt werden. Wegen der Größe
1
1 Einleitung
des Liederkatalogs bereiten sich Musiker nicht auf jedes einzelne Lied vor, sondern
entwickeln durch Üben an verschiedenen Liedern ein allgemeines Verständnis, wie
ein einzelnes Akkordsymbol oder eine Akkordsymbol-Folge auf dem Instrument
gespielt wird, um einen bestimmten Klang zu erzielen [Aeb67, S. 3].
Eine andere Vorgehensweise ist, für alle Akkordsymbole festzulegen, in welcher
Lage sie gespielt werden. Dieser Arbeitsschritt heißt Tonsatz und ist verbreitet,
wenn das Lied in einem größeren Zusammenhang (zum Beispiel Konzert) aufgeführt wird. Ein weiterer Grund kann sein, dass das Stück anspruchsvoll ist und der
Musiker seine Aufmerksamkeit beim Spielen auf andere Dinge richten möchte.
Theoretisch ist die Anzahl der Möglichkeiten, ein Akkordsymbol auf einem Instrument zu spielen, exponentiell zur Anzahl der zu spielenden Töne. In der Praxis
sind die Möglichkeiten durch technische Grenzen des Instruments sowie durch anatomische Grenzen und ästhetische Ziele des Musikers eingeschränkt.
1.3 Zielsetzung
Diese Arbeit beschreibt einen Algorithmus, der zu einer Folge von Akkordsymbolen einen optimalen Tonsatz durchführt und Fingersätze zuweist. Die Optimalität
ist bezüglich vorgegebener Regeln, die jeweils einer Akkordlage oder einer Folge
von Akkordlagen eine Bewertungszahl zuordnen. Außerdem wird durch vorgegebene Constraints (zum Beispiel anatomische Möglichkeiten des Instrumentalisten)
eingeschränkt, welche Akkordlagen überhaupt infrage kommen.
Der Algorithmus soll Instrumentalisten dabei helfen, für Lieder oder Passagen
innerhalb eines Liedes spielbare und den ästhetischen Zielen entsprechende Akkordlagen zu finden.
2
1 Einleitung
1.4 Vorhandene Lösungen
Vorhandene Lösungen zu ähnlichen Problemen lassen sich in folgende Kategorien
einteilen:
• Hinzufügen von Akkorden zu einer gegebenen Melodie [RP98; KMH13; PR01].
Dieses Problem wird Automatic Harmonization Problem (AHP) genannt.
• Erzeugen von Akkordsymbolen ohne Vorgabe einer Melodie [HS11; EP10].
• Funktionsharmonische Analyse von Akkordsymbolen [Haa+11; LJ83].
• Erzeugen eines Fingersatzes zu einem gegebenen Tonsatz [KNR07; YKS07].
• Erzeugen von Gitarrentabulaturen zu mehrstimmigen Musikstücken [TP05].
Ein genetischer Algorithmus zur Erzeugung spielbarer Gitarrentabulaturen [TP05]
hat ein ähnliches Ziel wie diese Arbeit: Die Töne eines mehrstimmigen Musikstücks
werden den Saiten einer Gitarre so zugewiesen, dass das Ergebnis angenehm spielbar ist. Die Bewertung erfolgt durch eine Fitnessfunktion, wobei jeweils ein Lösungskandidat eine mögliche Tabulatur für das gesamte Musikstück ist. Der Algorithmus findet im Allgemeinen lokale Optima und betrachtet immer das gesamte
Musikstück.
Der in dieser Arbeit beschriebene Algorithmus findet ein globales Optimum und
betrachtet Teilabschnitte eines Musikstücks. Die Länge der Teilabschnitte ist variabel und kann so gewählt werden, dass das gesamte Musikstück betrachtet wird.
Außerdem werden keine Gitarrentabulaturen erzeugt, sondern ein Notensatz mit
Klavierfingersätzen.
1.5 Lösungsplan
Das Problem wird als ein kürzeste-Wege-Problem in einem Graphen modelliert.
Ein kürzester Weg wird durch eine Implementierung in Haskell mit der Functional
Graph Library (FGL) [Erw] bestimmt.
3
2 Beschreibung des Algorithmus
2.1 Datenmodell
In diesem Abschnitt werden die verwendeten Datentypen definiert. Der entsprechende Typ der Haskell-Implementierung1 ist jeweils als Fußnote vermerkt.
Sei P die Menge der Töne2 (engl. pitch class) ohne enharmonische Verwechslung,
definiert als:
P = {pC , pC♯ , pD , pD♯ , pE , pF , pF♯ , pG , pG♯ , pA , pA♯ , pB }
(2.1)
Eine Tonhöhe kann durch ein Paar bestehend aus Ton und Oktave eindeutig beschrieben werden. Im MIDI-Standard werden Oktaven als natürliche Zahlen von 0
aufsteigend dargestellt. Der Standard beschreibt außerdem Tonhöhen durch die natürlichen Zahlen 0 (entspricht (pC , 0)) bis 127 (entspricht (pG , 10)) [95, S. 10]. Diese
Konvention wird im folgenden übernommen und verallgemeinert, sodass auch Tonhöhen außerhalb des Intervalls {0, . . . , 127} darstellbar sind. Also werden Oktaven
und Tonhöhen als ganze Zahlen dargestellt.
Die Menge der Tonhöhen3 (engl. pitch) ist die Menge der ganzen Zahlen:
Pabs = Z
1
(2.2)
Die Haskell-Implementierung ist unter http://github.com/martinfinke/Harmony verfügbar.
Entspricht dem Typ Types.PitchClass.
3
Entspricht dem Typ Types.Pitch.
2
4
2 Beschreibung des Algorithmus
Die Funktion pitch ordnet einem Paar aus Ton und Oktave eine Tonhöhe zu:4
pitch : (P × Z) → Pabs
(2.3)
pitch(p, o) = 12 · o + pitchClassOffset(p)
mit:
pitchClassOffset : P → Z
{
(pC , 0), (pC♯ , 1), (pD , 2), (pD♯ , 3),
pitchClassOffset = (pE , 4), (pF , 5), (pF♯ , 6), (pG , 7),
(pG♯ , 8), (pA , 9), (pA♯ , 10), (pB , 11)
(2.4)
}
Die Funktion pitch entspricht zwischen (pC , 0) und (pG , 10) dem MIDI-Standard.
Beispiel 2.1:
Für den Ton pF♯ in der Oktave 4 ist die Tonhöhe:
pitch(pF♯ , 4) = 12 · 4 + pitchClassOffset(pF♯ ) = 48 + 6 = 54.
Die Menge der Tongeschlechter5 (engl. mode) ist definiert als:
M = {Minor, Major}
(2.5)
Die Menge der Spannungstöne6 (engl. tension) ist wie folgt definiert:
T = {♭5 , ♯5 , ♭6 , 6 , ♭7 , 7 , maj7 , ♭9 , 9 , ♯9 , 11 , ♯11 , ♭13 , 13 }
(2.6)
Wobei die Elemente aus T als Symbole zu verstehen sind, nicht als Zahlen.
4
pitch entspricht der Funktion Types.toPitch. pitchClassOffset entspricht der Funktion
fromEnum der Enum-Instanz von PitchClass.
5
Entspricht dem Typ Types.MajMin.
6
Entspricht dem Typ Types.Tension.
5
2 Beschreibung des Algorithmus
Die Menge der Akkordsymbole7 (engl. chord symbol) ist definiert als:
{
C = (p, m, b, T ) | p ∈ P, m ∈ M ∪ {Nothing}, b ∈ P ∪ {Nothing}, T ⊆ T
}
(2.7)
Ein Akkordsymbol C ∈ C besteht also aus:
• einer Grundtonart p
• einem optionalen Tongeschlecht m (Nothing bedeutet, dass der Akkord kein
Tongeschlecht hat)
• einer optionalen Basstonangabe b (Nothing bedeutet, dass der Basston beliebig gewählt werden kann)
• einer Menge von Spannungstönen T .
Beispiel 2.2:
Die in der Musiknotation übliche Schreibweise G7♯9 für einen G-Dur-Septakkord
mit übermäßiger None entspricht dem Akkordsymbol
(
)
C = pG , Major, Nothing, {7 , ♯9 } .
Ein Akkordsymbol beschreibt, welche Töne gespielt werden müssen. Durch die
Wahl einer Oktave für jeden zu spielenden Ton entsteht eine endliche Menge von
Tonhöhen, die Lage genannt wird. Die Menge der Lagen8 ist:
L = {L | L ⊂ Pabs }
(2.8)
Beispiel 2.3:
Eine mögliche Lage für das Akkordsymbol C aus Beispiel 2.2 ist
{
L = pitch(pG , 3), pitch(pB , 3), pitch(pD , 4), pitch(pF , 4), pitch(pA♯ , 4)
}
= {43, 47, 50, 53, 58}.
Es gibt für ein Akkordsymbol mehrere mögliche Lagen. Beim Klavier legt die Lage
fest, welche Tasten beim Spielen des Akkords gedrückt werden. Es ist nicht festge7
8
Entspricht dem Typ Types.ChordSymbol.
Entspricht dem Typ Types.Chord.
6
2 Beschreibung des Algorithmus
legt, welcher Finger (welcher Hand) welche Tonhöhe spielt. Ein Fingersatz ordnet
Tonhöhen Finger zu. Dabei werden Finger durch die natürlichen Zahlen 1 bis 5
bezeichnet, wobei der Daumen der Zahl 1 entspricht. Den anderen vier Fingern
werden entsprechend aufsteigende Zahlen zugeordnet: Der Zeigefinger entspricht
der 2 und der kleine Finger der 5. Das entspricht der üblichen Konvention für
Klavierfingersätze [Her09, S. 24]. Also ist die Menge der Finger:9
F = {1, 2, 3, 4, 5}
(2.9)
Eine Hand ist eine partielle Abbildung von Fingern auf absolute Tonhöhen. Damit
ist die Menge der Hände:10
H = {h | h : F ,→ Pabs }
(2.10)
Beispiel 2.4:
Ein möglicher Fingersatz zur Lage L aus Beispiel 2.3 ist die Hand
{
}
h = (5, 43), (3, 47), (4, 50), (1, 53), (2, 58)
Da der Algorithmus mit Folgen nacheinander zu spielender Hände arbeitet, wird
außerdem die Menge der Hand-Folgen11 definiert als:
{
S = (h1 , . . . , hn ) | n ∈ N und hi ∈ H für i = 1, . . . , n
9
}
(2.11)
Entspricht dem Typ Types.Finger.
Entspricht dem Typ Types.Hand.
11
Entspricht Types.SubProgression. Die Bezeichnung S wurde gewählt, da H und F bereits
vergeben sind.
10
7
2 Beschreibung des Algorithmus
Beispiel 2.5:
Die Hand-Folge
s=
=
({
} {
})
(1, pitch(pC , 5)), (5, pitch(pG , 5)) , (1, pitch(pC , 5)), (5, pitch(pE , 5))
({
} {
(1, 60), (5, 67) , (1, 60), (5, 64)
})
beschreibt, dass der erste und fünfte Finger zuerst eine Quinte und danach eine
große Terz spielen.
2.2 Vorgehensweise
Der Algorithmus12 generiert zu einer Folge von Akkordsymbolen (C1 , . . . , Cn ) eine
optimale Hand-Folge Hands ∗ = (h∗1 , . . . , h∗n ). Dabei wird zunächst für jedes Akkordsymbol die Menge möglicher Lagen erzeugt. Aus jeder Lage entsteht durch
Hinzufügen eines Fingersatzes eine Hand. Dann werden aus den Händen aufeinanderfolgender Akkordsymbole alle Hand-Folgen für diese Akkordsymbole generiert.
Diese Hand-Folgen sind die Knoten eines gewichteten Graphen G = (V, E). Die
Knoten werden so durch Kanten verbunden, dass ein Weg durch den Graphen eine mögliche Hand-Folge für die Akkordsymbolfolge liefert. Das Überqueren einer
Kante bedeutet, dass zu den bereits gespielten Händen genau eine weitere dazukommt. Das Gewicht der Kante sagt aus, wie unbequem spielbar beziehungsweise
unharmonisch (gemäß gegebener Bewertungsregeln) das Spielen der neuen Hand
ist. Ein kürzester13 Weg durch den Graphen liefert eine optimale Hand-Folge.
Im Folgenden ist n ∈ N die Länge der gegebenen Akkordsymbolfolge. Die Zahl
i = 1, . . . , n beschreibt eine Position in der Folge.
12
13
Entspricht der Funktion HandProgressionGraph.optimalHandProgression.
Mit kürzester Weg ist hier ein Weg gemeint, der die Summe über die Gewichte der überquerten
Kanten minimiert.
8
2 Beschreibung des Algorithmus
2.3 Erzeugung möglicher Hände
In diesem Abschnitt wird beschrieben, wie zu einem einzelnen Akkordsymbol
C = (p, g, b, T ) die Menge möglicher Hände H ⊆ H erzeugt wird14 .
Zuerst wird die Menge relativer Halbtonabstände Obasic ⊂ N erzeugt:
{
}
Obasic = {0} ∪ tensionToSemitones(t) | t ∈ T ∪


{7}
, falls ♭5 ∈
/T

{}
, sonst
(2.12)
Wobei:
tensionToSemitones : T → N
{
(♭5 , 6), (♯5 , 8),
(♭6 , 8), (6 , 9),
tensionToSemitones =
(♭7 , 9), (7 , 10), (maj7 , 11),
(2.13)
(♭9 , 1), (9 , 2), (♯9 , 3),
(11 , 5), (♯11 , 6),
(♭13 , 8), (13 , 9)
}
Zu beachten ist, dass tensionToSemitones nicht injektiv ist, zum Beispiel:
tensionToSemitones(♯5 ) = tensionToSemitones(♭6 ) = tensionToSemitones(♭13 )).
In Obasic kommt aber, da es eine Menge ist, kein Element mehrfach vor.
Obasic enthält den Grundton (dargestellt durch die Zahl 0) sowie für jeden Spannungston seinen Halbtonabstand zum Grundton. Es wird außerdem eine Quinte
hinzugefügt (Halbtonabstand 7), sofern es sich nicht um einen verminderten Akkord handelt, also keine verminderte Quinte (♭5 ) als Spannungston angegeben ist.
Spannungstöne, die mehr als eine Oktave über dem Grundton liegen, werden um
eine Oktave nach unten transponiert.
14
Entspricht der Funktion GenerateChords.handsForChordSymbol.
9
2 Beschreibung des Algorithmus
Beispiel 2.6:
Die Menge relativer Halbtonabstände für das Akkordsymbol C aus Beispiel 2.2
{
}
ist Obasic = {0} ∪ tensionToSemitones(t) | t ∈ {7 , ♯9 } ∪ {7} = {0, 10, 3, 7}.
Zu Obasic wird, falls ein Tongeschlecht angegeben wurde, eine entsprechende (kleine
oder große) Terz hinzugefügt. Das ergibt die Halbtonabstandsmenge Omode :



Obasic



Omode =
, wenn g = Nothing
Obasic ∪ {3}




O
basic ∪ {4}
(2.14)
, wenn g = Minor
, wenn g = Major
Beispiel 2.7:
Das Akkordsymbol C aus Beispiel 2.2 beschreibt einen Dur-Akkord. Daher ist
Omode = Obasic ∪ {4} = {0, 10, 3, 7, 4}.
Anschließend wird jeder Halbtonabstand aus Omode entweder nicht verändert, oder
um eine Oktave nach oben oder unten transponiert. Dadurch entstehen verschiedene Möglichkeiten, die Töne des Akkords anzuordnen. Es seien o1 , . . . , o|Omode | ∈
Omode alle Elemente aus Omode . Dann ist die Menge der Variationsmöglichkeiten
für einen Halbtonabstand o ∈ Omode definiert als:
Ovar,k = {ok , ok + 12, ok − 12}
(2.15)
(k = 1, . . . , |Omode |)
Beispiel 2.8:
Sei o4 = 7 der Halbtonabstand der Quinte aus Omode (Beispiel 2.7). Dann ist
Ovar,4 = {7, 19, −5}.
Die Menge der Variationsmöglichkeiten für einen Akkord mit den Halbtonabständen Omode ist:
{
Ocomb = {ovar,k | ovar,k ∈ Ovar,k , k = 1, . . . , |Omode |}
10
}
(2.16)
2 Beschreibung des Algorithmus
Beispiel 2.9:
Für die Halbtonabstandsmenge O = {0, 4} ist die Menge der Variationsmöglichkeiten:
{
Ocomb = {0, 4}, {0, 16}, {0, −8},
{12, 4}, {12, 16}, {12, −8},
{−12, 4}, {−12, 16}, {−12, −8}
}
Die relativen Halbtonabstände werden in Tonhöhen umgewandelt. Dabei wird der
Grundton 0 auf die MIDI-Notennummer mit Grundtonart p in der dritten Oktave abgebildet. Alle anderen Halbtonabstände werden um den gleichen Betrag
transponiert. Das ergibt die Menge der Lagen LC ⊂ L für das Akkordsymbol.15
Beispiel 2.10:
Für die Halbtonabstandsmenge O = {0, 3, 7} und die Grundtonart p = pD ist
{
}
die Lage L = pitch(pD , 3), pitch(pD , 3) + 3, pitch(pD , 3) + 7 = {38, 41, 45}.
Wenn im Akkordsymbol eine Basstonangabe vorhanden ist (b ̸= Nothing), werden
aus LC nur die Lagen übernommen, deren tiefster Ton der Angabe entspricht:
{
}
LC,slash = L ∈ LC | ∃o ∈ Z : pitch(b, o) = min L
(2.17)
Beispiel 2.11:
Für die Lage L aus Beispiel 2.10 und eine Basstonangabe b = pD gilt:
L ∈ LC,slash , denn pitch(pD , 3) = 38 = min L.
Jede Lage wird in eine Hand umgewandelt, indem den tiefsten fünf Tönen (sofern
vorhanden) die Finger 5, 4, . . . , 1 zugeordnet werden:
toHand : L → H
{
toHand(L) = (5, min L), (4, min(L \ min L)), . . .
15
Entspricht der Funktion GenerateChords.chordsForChordSymbol.
11
}
(2.18)
2 Beschreibung des Algorithmus
Beispiel 2.12:
{
}
Für die Lage L aus Beispiel 2.10 ist die Hand H = toHand(L) = (5, 38), (4, 41), (3, 45) .
2.4 Erzeugung möglicher Sub-Folgen
In diesem Abschnitt wird erklärt, wie der Algorithmus zu Teilabbschnitten der Akkordfolge mögliche Hand-Folgen erzeugt. Diese werden als Sub-Folgen bezeichnet.
Die Länge dieser Sub-Folgen ist die maximale Anzahl aufeinanderfolgender Akkorde, die eine Regel bewerten kann. Sie wird im Folgenden durch die Konstante
l festgelegt,16 wobei l ∈ N \ {0}.
Sei Hi die Menge möglicher Hände an der Song-Position i (der erste zu spielende
Akkord ist bei i = 1). Dann wird für jede Position i die Menge möglicher SubFolgen erzeugt:17
{
∀i : Si = (hmax{1,i−l+1} , . . . , hi−1 , hi ) | hj ∈ Hj für j = 1, . . . , n
}
(2.19)
Ein Si enthält alle Möglichkeiten, einen Abschnitt der Akkordfolge zu greifen. Die
Länge der Tupel eines Si richtet sich nach l und danach, ob i < l: S1 enthält nur
1-Tupel, und alle Si für i ≥ l enthalten nur l-Tupel.
Beispiel 2.13:
Für einen Song der Länge n = 3 mit den Mengen möglicher Hände
H1 = {h1,1 }, H2 = {h2,1 , h2,2 }, H3 = {h3,1 } sind mit l = 2 die Mengen möglicher
Sub-Folgen:
{
}
S1 = (h1,1 )
{
}
{
}
S2 = (h1,1 , h2,1 ), (h1,1 , h2,2 )
S3 = (h2,1 , h3,1 ), (h2,2 , h3,1 ) .
16
17
Entspricht HandProgressionGraph.subProgressionLength.
Entspricht HandProgressionGraph.makeSubProgressions.
12
2 Beschreibung des Algorithmus
Die Knotenmenge V des Graphen besteht aus zwei Markierungsknoten für den
Anfang und das Ende der Akkordfolge, sowie allen Sub-Folgen aller Positionen i:
n
∪
V = {Start, End} ∪
(2.20)
Si
i=1
2.5 Verbindung der Sub-Folgen
In diesem Abschnitt wird beschrieben, wie die Kantenmenge E des Graphen erzeugt wird.18 Außerdem wird das Gewicht w(e) der Kanten definiert (e ∈ E).
Das Startsymbol wird mit allen Sub-Folgen der Position 1 verbunden:
{
E1 = (Start, s) | s ∈ S1
}
(2.21)
Außerdem werden alle Sub-Folgen an der Position n (also die letzten in der Akkordfolge) mit dem End-Knoten verbunden:
{
En+1 = (s, End) | s ∈ Sn
}
(2.22)
An allen anderen Position werden zwei Sub-Folgen benachbarter Positionen genau
dann verbunden, wenn sie das Prädikat precedes erfüllen:
{
}
Ei = (spred , scurr ) | spred ∈ Si−1 , scurr ∈ Si , precedes(spred , scurr )
(1 < i ≤ n)
18
Entspricht HandProgressionGraph.makeEdges.
13
(2.23)
2 Beschreibung des Algorithmus
Wobei:
precedes : (S × S) → {0, 1}


1, falls h1,u = h2,v−1 ∧






h1,u−1 = h2,v−2 ∧



precedes((h1,1 , . . . , h1,u ), (h2,1 , . . . , h2,v )) =
... ∧
h1,u−v+2 = h2,1
(2.24)









0, sonst
Das Prädikat precedes bestimmt, ob eine Sub-Folge s ∈ Si−1 vor einer anderen
s′ ∈ Si gespielt werden kann. Das ist genau dann der Fall, wenn die letzten v − 1
Hände von s gleich den ersten v − 1 Händen von s′ sind (wobei v die Länge von
s′ ist). Mit anderen Worten: Wenn alle Hände in s′ bis auf die letzte auch schon
am Ende von s gespielt wurden. Die Bedeutung einer Kante (s, s′ ) ist also, dass
die Hände aus s gespielt werden, und danach die letzte Hand aus s′ .
Beispiel 2.14:
Für die Sub-Folgen (h1,1 , h2,2 ), (h2,1 , h3,1 ) und (h2,2 , h3,1 ) aus Beispiel 2.13 gilt:
(
)
precedes (h1,1 , h2,2 ), (h2,1 , h3,1 ) = 0, da h2,2 ̸= h2,1 und
(
)
precedes (h1,1 , h2,2 ), (h2,2 , h3,1 ) = 1, da h2,2 = h2,2 .
Damit ist die Kantenmenge des Graphen:
E=
n+1
∪
(2.25)
Ei
i=1
Beispiel 2.15:
Für S1 , S2 , S3 aus Beispiel 2.13 ist die Kantemenge E = E1 ∪ E2 ∪ E3 ∪ E4 , mit:
{(
)}
E1 = Start, (h1,1 )
E2 =
E3 =
E4 =
{(
{(
{(
) (
)}
(h1,1 ), (h1,1 , h2,1 ) , (h1,1 ), (h1,1 , h2,2 )
) (
)}
(h1,1 , h2,1 ), (h2,1 , h3,1 ) , (h1,1 , h2,2 ), (h2,2 , h3,1 )
) (
(h2,1 , h3,1 ), End , (h2,2 , h3,1 ), End
14
)}
2 Beschreibung des Algorithmus
Die Funktion w : E → R≥0 ordnet Kanten des Graphen Gewichte zu. Das Gewicht
w(e) einer Kante e ∈ E ist:
w((spred , scurr )) =


0
, falls scurr = End

rate(scurr )
, sonst
(2.26)
Wobei die Funktion rate : S → R≥0 eine Sub-Folge nach bestimmten Regeln bewertet.19 Die Anwendung einer Regel ergibt eine Bewertung in Form einer positiven
reellen Zahl, wobei 0 als neutrales Element der Addition bedeutet, dass die Regel
perfekt eingehalten wurde. Wird eine Regel verletzt, wird eine Strafe penalty > 0
vergeben. rate wendet alle Regeln an und summiert die Strafen auf.
Eine Regel liefert auch immer dann die Bewertung 0, wenn die zu bewertende SubFolge für diese Regel zu kurz ist. Das kann nur für Sub-Folgen s ∈ Si mit i < l
eintreten.
2.6 Finden einer optimalen Hand-Folge
Der Algorithmus von Dijkstra [Dij59] wird benutzt, um im Graph G einen kürzesten Weg W ∗ vom Knoten Start zum Knoten End zu finden:20
W ∗ = (Start, s∗1 , . . . , s∗n , End)
(2.27)
(s∗i ∈ Si , i = 1, . . . , n)
Beispiel 2.16:
Es werden S1 , S2 , S3 aus Beispiel 2.13 sowie E aus Beispiel 2.15 verwendet. Des(
)
(
)
(
)
(
)
weiteren sei rate (h1,1 , h2,1 ) +rate (h2,1 , h3,1 ) > rate (h1,1 , h2,2 ) +rate (h2,2 , h3,1 ) .
(
)
Dann ist W ∗ = Start, (h1,1 ), (h1,1 , h2,2 ), (h2,2 , h3,1 ), End .
19
20
Entspricht RateSubProgression.totalRating.
Entspricht HandProgressionGraph.bestIndexPath.
15
2 Beschreibung des Algorithmus
Aus jeder Sub-Folge s∗i wird die letzte Hand ausgewählt. Das ergibt eine optimale
Hand-Folge:
(
)
Hands ∗ = last(s∗1 ), . . . , last(s∗n ) ,
(
)
wobei last (h1 , . . . , hv ) = hv
Beispiel 2.17:
Für W ∗ aus Beispiel 2.16 ist Hands ∗ = (h1,1 , h2,2 , h3,1 ).
16
(2.28)
3 Ergebnisse
Die Haskell-Implementation des Algorithmus wurde mit den Akkordsymbolfolgen
neun verschiedener Jazz-Standards getestet.1 Zur Berechnung der Kantengewichte
wurden folgende Bewertungskriterien verwendet:2
• Bestrafung, wenn ein Finger um mehr als eine große Terz springt
• Bestrafung, wenn die höchste Stimme um mehr als eine Quarte springt
• Bestrafung, wenn ein Finger über eine schwarze Taste springen muss
• Bestrafung, wenn ein Finger eine weiße Taste im Bereich zwischen zwei
schwarzen Tasten treffen muss
• Bestrafung, wenn sich der Greifumfang zweier aufeinanderfolgender Lagen
um mehr als eine Quinte unterscheidet
• Bestrafung von Clustern
• Bestrafung, wenn Akkordtöne mehr als eine Quinte voneinander entfernt
liegen
Im Folgenden wird beispielhaft der Song »Donna Lee« von Charlie Parker betrachtet [04, S. 123]. Die Akkordsymbole sind im Real Book angegeben als A♭maj7 , F 7 , . . . , E♭7 .
1
Die IO-Aktion LilypondOutput.allExamplesToPdf erzeugt zu jedem der neun Beispiele ein
Notenblatt wie Abbildung 3.1 im PDF-Format.
2
Die Bewertungsfunktionen sind in RateSubProgression.allSubProgressionRaters.
17
3 Ergebnisse
Die Eingabe für das Programm ist (verkürzt dargestellt) der Haskell-Ausdruck:3
[ChordSymbol aFlat (Just Major) [MajorSeventh] Nothing,
ChordSymbol F (Just Major) [Seventh] Nothing,
...
ChordSymbol eFlat (Just Major) [Seventh] Nothing]
Der Aufruf optimalHandProgression donnaLee liefert eine Liste von Hands, wobei
jede Hand eine Abbildung von Finger auf Pitch ist. Das ist die Ausgabe des
Programms:
[fromList [(2,Pitch 44),(3,Pitch 43),(4,Pitch 39),(5,Pitch 36)],
fromList [(2,Pitch 45),(3,Pitch 41),(4,Pitch 39),(5,Pitch 36)],
...
fromList [(2,Pitch 51),(3,Pitch 49),(4,Pitch 46),(5,Pitch 43)]]
Mit den LilyPond-Bindings für Haskell [Hog] können daraus Noten gerendert werden (Abbildung 3.1).
Die Gesamtkosten (als Summe über die Gewichte aller überquerten Kanten) sind
163,0.4 Die Notation zeigt, dass die Akkordlagen einhändig spielbare Lagen sind,
für die sich ein Pianist entscheiden würde. Auffällig sind Auf- und Abwärtsbewegungen der Akkordlagen (zum Beispiel aufwärts in Takt 1, sprunghaft abwärts in
Takt 3). Ähnliche Bewegungen waren auch bei den Ausgaben zu anderen Songs
vorhanden. Im Allgemeinen reduziert ein Pianist solche Bewegungen, um Kollisionen mit einer darüber gespielten Melodiestimme zu vermeiden.
Wird die Bedingung hinzugefügt, dass alle Akkorde in Grundstellung sein müssen
(also der Grundton der tiefste Ton ist), sind die Kosten 386,0.5 Abbildung 3.2
zeigt die gerenderte Ausgabe. Um jeden Akkord in Grundstellung zu spielen, sind
größere Sprünge notwendig, wodurch erhöhte Kosten entstehen.
3
Dieser Ausdruck ist ExampleChordProgressions.donnaLee.
Der Wert wird berechnet mit: minimumCost donnaLee.
5
Berechnung mit: minimumCost (forbidInversions donnaLee).
4
18
3 Ergebnisse
A
’
7 9
4
7
F
maj7
~ ~ B
7
7
B -
7
F
B
F- B
7
E
7 A maj7 E -7
~ ~ ~ ~ ~ ~ ~ 7
E
~ ~ ~ ~ ~ ~ 7
ø
G
C
7 B -7
o7
B
A
~ ~ maj7
C-
~ ~ ~ ~ ~ ~ 7
~~ 7
F
B
7
7
D
7
7
B -
ø
G
E
maj7 D -7 G 7 A maj7
~ ~ ~ ~ 7
A
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ’
7 9
C
~ ~ ~ F
D
maj7
F-
7
7
C
F-
7
E
~ ~ ~ ’
7 9
F
B -
~
~ ~ ~ ~ ~ ~ 7
7
Abbildung 3.1: Mit LilyPond gerenderte optimale Hand-Folge (ohne Fingersätze) zu
den 37 Akkordsymbolen des Songs »Donna Lee«. Die Akkordsymbole
entsprechen denen im Real Book und wurden von Hand hinzugefügt. Da
der Algorithmus keine Enharmonik berücksichtigt, sind auch ♭-Tonarten
mit Kreuz (♯) notiert.
Die in Gleichung 2.18 vorgestellte Zuweisung von Fingersätzen zu Tonhöhen hat
Nachteile bei Lagen mit weniger als 5 Tonhöhen: Wenn eine Akkordlage zum Beispiel aus nur zwei Tonhöhen besteht, die eine Oktave voneinander entfernt liegen,
werden den Tonhöhen die Finger 5 und 4 zugewiesen. Die Hand wird als unspielbar
bewertet, da der Abstand zwischen den beiden Fingern zu groß ist. Die Lage wäre
aber mit den Fingern 5 und 1 problemlos greifbar. Ein weiteres Problem bei der
Umwandlung einer Lage in eine Hand ist, dass nur die tiefsten fünf Töne einer Lage
übernommen werden. Dadurch werden Akkordsymbole mit mehr als fünf Tönen
unvollständig umgesetzt.
Die Berechnung einer optimalen Hand-Folge für »Donna Lee« mit l = 2 benötigte
auf einem 1,7 GHz Intel Core i5 und 4 GB 1333 MHz DDR3-Arbeitsspeicher
176 ms, davon 11 ms für System-Aufrufe.6 Setzen von l = 3 erhöhte die benötigte
Zeit auf 2,68 s, mit l = 4 stieg sie auf 1 min 41 s. Erhöhen von l erhöht die
Knotenanzahl an jeder Song-Position exponentiell, was den starken Anstieg der
Laufzeit erklärt. Durch die Verwendung des Dijkstra-Algorithmus ist die Laufzeit
bei konstantem l polynomial bezüglich der Anzahl n der Akkordsymbole.
6
Es wurde der Haskell-Compiler GHC in Version 7.8.3 mit dem Parameter -O3 verwendet.
Music engraving by LilyPond 2.18.2—www.lilypond.org
19
3 Ergebnisse
A
~~ ~ ~
B
B -
B
B
C- F
B E A
~
~
~
~
~
~
~
~ ~ ~ ~ ~ ~ ~ ø
G
7
B
7
7 B -7 ~ E 7 A maj7 E -7 D7 D maj7 D -7 G 7 A maj7
~
~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ 7
F
ø
7
7 ’9
7
7
7
7 ~ E 7 A maj7 F7
B
G
C
FC
F~ ~ ~ ~~ ~ ~ ~ ~ ~ ~ ~~ ~ ~ ~
’
7 9
F
4
maj7
7
C
F-
7
o7
7
7
7
7
maj7
7 ~ E 7
~ ~ ~ ~~ ~ ’
7 9
F
B -
Abbildung 3.2: Mit LilyPond gerenderte optimale Hand-Folge für »Donna Lee«, unter
der Bedingung, dass alle Akkorde in Grundstellung sein müssen.
20
4 Ausblick
Eine mögliche Verbesserung des Algorithmus ist eine andere Fingersatzberechnung.
Für die Hand-Bewertung werden bereits Abstandsmaße zwischen Fingern benutzt.
Diese können benutzt werden, um zu einer Lage Fingersätze zu finden, die spielbar
sind.
Die verlustbehaftete Umsetzung von Akkordsymbolen mit mehr als fünf Tönen
kann verbessert werden. Eine Möglichkeit ist das Bevorzugen wichtiger Tonhöhen.
Es ist zum Beispiel üblich, bei Akkorden mit vielen Tonhöhen die Quinte nicht
zu spielen, da sie am wenigsten zum Klang beiträgt. Die Wichtigkeit verschiedener Tonhöhen und Spannungstöne muss durch den Benutzer global oder für jedes
Akkordsymbol anpassbar sein.
Da anatomische Grenzen und musikalischer Geschmack vom Benutzer abhängen,
müssen für eine praktische Anwendung Constraints wie der maximale Fingerabstand vom Benutzer einstellbar sein. Außerdem müssen Bewertungsregeln unterschiedlich gewichtet in die Beurteilung eingehen, da je nach Anwendungsfall andere
musikalische Merkmale wichtig sind.
Der Algorithmus ist auf andere Akkordinstrumente (zum Beispiel Gitarre) übertragbar, da die Bewertung von Händen vom Rest des Algorithmus getrennt ist. Es
ist zu überprüfen, ob sich die Merkmale anderer Instrumente mit dem vorhandenen
Datenmodell darstellen lassen.
21
Literatur
[04]
The Real Book. 6. Aufl. Hal Leonard Corporation, Sep. 2004.
[95]
MIDI 1.0 Detailed Specification. Document Version 4.2. MIDI Manufacturers Association Incorporated, Sep. 1995.
[Aeb67]
Jamey Aebersold. Volume 1, How to Play Jazz and Improvise: Revised
6th Edition. Jamey Aebersold Jazz. Jamey Aebersold Jazz Incorporated, 1967.
[Deb07]
J. Debbeler. Harmonie und Perspektive: die Entstehung des neuzeitlichen abendländischen Kunstmusiksystems. Aesthetica theatralia. epodiumVerlag, 2007.
[Dij59]
Edsger. W. Dijkstra. »A note on two problems in connexion with
graphs.« In: Numerische Mathematik 1 (1959), S. 269–271.
[EP10]
Arne Eigenfeldt und Philippe Pasquier. »Realtime generation of harmonic progressions using controlled Markov selection«. In: Proceedings
of ICCC-X-Computational Creativity Conference. 2010.
[Erw]
Martin Erwig. FGL/Haskell - A Functional Graph Library for Haskell.
url: http://web.engr.oregonstate.edu/~erwig/fgl/haskell/
(besucht am 24. 03. 2015).
[Haa+11] W. Bas de Haas u. a. »HarmTrace: Improving harmonic similarity estimation using functional harmony analysis«. In: In Proceedings of the
12th International Society for Music Information Retrieval Conference.
2011, S. 67–72.
[Her09]
Alan Hersh. A Pianist’s Dictionary: Reflections on a Life. Hamilton
Books, 2009.
I
[Hog]
Hans Hoglund. lilypond: Bindings to Lilypond | Hackage. url: https:
//hackage.haskell.org/package/lilypond (besucht am 24. 03. 2015).
[HS11]
Dorien Herremans und Kenneth Sörensen. A variable neighbourhood
search algorithm to generate first species counterpoint musical scores.
Working Papers 2011017. University of Antwerp, Faculty of Applied
Economics, Okt. 2011.
[Kár65]
Ottó Károlyi. Introducing Music. Penguin Books, 1965.
[KMH13]
Hendrik Vincent Koops, José Pedro Magalhães und W. Bas de Haas.
»A Functional Approach to Automatic Melody Harmonisation«. In:
Proceedings of the First ACM SIGPLAN Workshop on Functional Art,
Music, Modeling & Design. FARM ’13. Boston, Massachusetts, USA:
ACM, 2013, S. 47–58.
[KNR07]
Alia Al Kasimi, Eric Nichols und Christopher Raphael. »A Simple Algorithm for Automatic Generation of Polyphonic Piano Fingerings«.
In: Proceedings of the 8th International Conference on Music Information Retrieval, Vienna, Austria, September 23-27. Österreichische
Computer Gesellschaft, 2007, S. 355–356.
[LJ83]
Fred Lerdahl und Ray Jackendoff. A generative theory of tonal music.
Cambridge. MA: The MIT Press, 1983.
[PR01]
Francois Pachet und Pierre Roy. »Musical Harmonization with Constraints: A Survey«. In: Constraints 6.1 (Jan. 2001), S. 7–19.
[RP98]
R. Ramirez und J. Peralta. »A constraint-based melody harmonizer«.
In: Workshop on Constraints for Artistic Applications. 1998.
[TP05]
D. R. Tuohy und W. D. Potter. »A genetic algorithm for the automatic generation of playable guitar tablature«. In: Proceedings of the
International Computer Music Conference. 2005, S. 499–502.
[YKS07]
Yuichiro Yonebayashi, Hirokazu Kameoka und Shigeki Sagayama. »Automatic Decision of Piano Fingering Based on Hidden Markov Models«.
In: Proceedings of the 20th International Joint Conference on Artifical
Intelligence. IJCAI’07. Hyderabad, India: Morgan Kaufmann Publishers Inc., 2007, S. 2915–2921.