| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Building complicated functions
Dieser Abschnitt zeigt, wie man Information zusammensucht, um komplizierte musikalische Funktionen zu erstellen.
| 1.3.1 Musikalische Funktionen darstellen | ||
| 1.3.2 Eigenschaften von Musikobjekten | ||
| 1.3.3 Verdoppelung einer Note mit Bindebögen (Beispiel) | ||
| 1.3.4 Artikulationszeichen zu Noten hinzufügen (Beispiel) |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Displaying music expressions
Wenn man eine musikalische Funktion erstellt, ist es oft
hilfreich sich anzuschauen, wie musikalische Funktionen
intern gespeichert werden. Das kann mit der Funktion
\displayMusic erreicht werden:
{
\displayMusic { c'4\f }
}
|
zeigt:
(make-music
'SequentialMusic
'elements
(list (make-music
'NoteEvent
'articulations
(list (make-music
'AbsoluteDynamicEvent
'text
"f"))
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))))
|
Normalerweise gibt LilyPond diese Ausgabe auf der Konsole mit allen anderen Nachrichten aus. Um die wichtigen Nachrichten in einer Datei zu speichern, kann die Ausgabe in eine Datei umgeleitet werden:
lilypond file.ly >display.txt |
Mit LilyPond- und Scheme-Magie kann man LilyPond anweisen, genau diese Ausgabe an eine eigene Datei zu senden:
{
#(with-output-to-file "display.txt"
(lambda () #{ \displayMusic { c'4\f } #}))
}
|
Mit etwas Umformatierung ist die gleiche Information sehr viel einfacher zu lesen:
(make-music 'SequentialMusic
'elements (list
(make-music 'NoteEvent
'articulations (list
(make-music 'AbsoluteDynamicEvent
'text
"f"))
'duration (ly:make-duration 2 0 1/1)
'pitch (ly:make-pitch 0 0 0))))
|
Eine musikalische { ... }-Sequenz hat die Bezeichnung
SequentialMusic und ihre inneren Ausdrücke werden als
Liste in seiner 'elements-Eigenschaft gespeichert. Eine
Note ist als als ein EventChord-Objekt dargestellt (welches Dauer und
Tonhöhe speichert) und zusätzliche Information enthält (in
diesem Fall ein AbsoluteDynamicEvent mit einer
"f"-Text-Eigenschaft).
\displayMusic gibt die Noten aus, die dargestellt werden, sodass
sie sowohl angezeigt als auch ausgewertet werden. Um die Auswertung zu
vermeiden, kann \void vor \displayMusic geschrieben werden.
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Music properties
TODO – make sure we delineate between music properties, context properties, and layout properties. These are potentially confusing.
Schauen wir uns ein Beispiel an:
someNote = c' \displayMusic \someNote ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1/1) 'pitch (ly:make-pitch 0 0 0)) |
Das NoteEvent-Objekt ist die Repräsentation von someNote.
Einfach. Wie fügt man denn ein c’ in einen Akkorde ein?
someNote = <c'>
\displayMusic \someNote
===>
(make-music
'EventChord
'elements
(list (make-music
'NoteEvent
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 0 0))))
|
Jetzt ist das NoteEvent-Objekt das erste Objekt der
'elements-Eigenschaft von someNote.
Die display-scheme-music-Funktion ist die Funktion, die von
\displayMusic eingesetzt wird, um die Scheme-Repräsentation
eines musikalischen Ausdrucks anzuzeigen.
#(display-scheme-music (first (ly:music-property someNote 'elements))) ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1/1) 'pitch (ly:make-pitch 0 0 0)) |
Danach wird die Tonhöhe der Note von der 'pitch-Eigenschaft
des NoteEvent-Objektes gelesen:
#(display-scheme-music
(ly:music-property (first (ly:music-property someNote 'elements))
'pitch))
===>
(ly:make-pitch 0 0 0)
|
Die Tonhöhe einer Note kann geändert werden, indem man diese
'pitch-Eigenschaft umdefiniert:
#(set! (ly:music-property (first (ly:music-property someNote 'elements))
'pitch)
(ly:make-pitch 0 1 0)) ;; Die Tonhöhen auf d' verändern.
\displayLilyMusic \someNote
===>
d'
|
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Doubling a note with slurs (example)
In diesem Abschnitt soll gezeigt, werden, wie man eine
Funktion erstellt, die eine Eingabe wie a
nach { a( a) } umdefiniert. Dazu wird zuerst die
interne Repräsentation der Musik betrachtet, die
das Endergebnis darstellt:
\displayMusic{ a'( a') }
===>
(make-music
'SequentialMusic
'elements
(list (make-music
'NoteEvent
'articulations
(list (make-music
'SlurEvent
'span-direction
-1))
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))
(make-music
'NoteEvent
'articulations
(list (make-music
'SlurEvent
'span-direction
1))
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch 0 5 0))))
|
Eine schlechte Nachricht ist, dass die
SlurEvent-Ausdrücke „innerhalb“
der Noten (in ihrer articulations-Eigenschaft) hinzugefügt werden müssen.
Jetzt folgt eine Betrachtung der Eingabe:
\displayMusic a' ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1/1) 'pitch (ly:make-pitch 0 5 0)))) |
In der gewünschten Funktion muss also dieser Ausdruck
kopiert werden (sodass zwei Noten vorhanden sind, die
eine Sequenz bilden), dann müssen SlurEvent
zu der 'articulations-Eigenschaft jeder Noten hinzugefügt
werden, und schließlich muss eine SequentialMusic
mit den beiden EventChords erstellt werden. Um zu
einer Eigenschaft etwas hinzuzufügen, ist es nützlich zu wissen, dass
eine nicht gesetzte Eigenschaft als '() gelesen wird, sodass
keine speziellen Überprüfungen nötig sind, bevor ein anderes
Element vor die articulations-Eigenschaft gesetzt wird.
doubleSlur = #(define-music-function (note) (ly:music?)
"Return: { note ( note ) }.
`note' is supposed to be a single note."
(let ((note2 (ly:music-deep-copy note)))
(set! (ly:music-property note 'articulations)
(cons (make-music 'SlurEvent 'span-direction -1)
(ly:music-property note 'articulations)))
(set! (ly:music-property note2 'articulations)
(cons (make-music 'SlurEvent 'span-direction 1)
(ly:music-property note2 'articulations)))
(make-music 'SequentialMusic 'elements (list note note2))))
|
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] | [Anfang] | [Inhalt] | [Index] | [ ? ] |
@translationof Adding articulation to notes (example)
Am einfachsten können Artikulationszeichen zu Noten hinzugefügt werden, indem man zwei musikalische Funktionen in einen Kontext einfügt, wie erklärt in (notation)Kontexte erstellen und referenzieren in Abschnitt ‘Kontexte erstellen und referenzieren’ in Notationsreferenz. Hier soll jetzt eine musikalische Funktion entwickelt werden, die das vornimmt. Daraus ergibt sich der zusätzliche Vorteil, dass diese musikalische Funktion eingesetzt werden kann, um eine Artikulation (wie etwa eine Fingersatzanweisung) einer einzigen Note innerhalb eines Akkordes hinzugefügt werden kann, was nicht möglich ist, wenn einfach unabhängige Noten ein einem Kontext miteinander verschmolzen werden.
Eine $variable innerhalb von #{...#} ist das
gleiche wie die normale Befehlsform \variable in
üblicher LilyPond-Notation. Es ist bekannt dass
{ \music -. -> }
|
in LilyPond nicht funktioniert. Das Problem könnte vermieden werden, indem das Artikulationszeichen an einen leeren Akkord gehängt wird:
{ << \music <> -. -> >> }
|
aber in diesem Beispiel soll gezeigt werden, wie man das in Scheme vornimmt. Zunächst wird die Eingabe und die gewünschte Ausgabe examiniert:
% Eingabe
\displayMusic c4
===>
(make-music
'NoteEvent
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))))
=====
% gewünschte Ausgabe
\displayMusic c4->
===>
(make-music
'NoteEvent
'articulations
(list (make-music
'ArticulationEvent
'articulation-type
"accent"))
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))
\displayMusic c4
===>
(make-music
'EventChord
'elements
(list (make-music
'NoteEvent
'duration
(ly:make-duration 2 0 1/1)
'pitch
(ly:make-pitch -1 0 0))))
|
Dabei ist zu sehen, dass eine Note (c4) als NoteEvent-Ausdruck
repräsentiert ist. Um eine Akzent-Artikulation hinzuzufügen, muss
ein ArticulationEvent-Ausdruck zu der Elementeigenschaft articulations
des NoteEvent-Ausdrucks hinzugefügt werden.
Um diese Funktion zu bauen, wird folgendermaßen begonnen:
(define (add-accent note-event)
"Add an accent ArticulationEvent to the articulations of `note-event',
which is supposed to be a NoteEvent expression."
(set! (ly:music-property note-event 'articulations)
(cons (make-music 'ArticulationEvent
'articulation-type "accent")
(ly:music-property note-event 'articulations)))
note-event)
|
Die erste Zeile definiert eine Funktion in Scheme: Die Bezeichnung
der Funktion ist add-accent und sie hat eine Variable
mit der Bezeichnung note-event. In Scheme geht der Typ
einer Variable oft direkt aus der Bezeichnung hervor (das ist auch
eine gute Methode für andere Programmiersprachen).
"Add an accent..." |
ist eine (englische) Beschreibung, was diese Funktion tut. Sie ist nicht unbedingt notwendig, aber genauso wie klare Variablen-Bezeichnungen ist auch das eine gute Methode.
Es kann seltsam scheinen, warum das Notenereignis direkt verändert wird,
anstatt mit einer Kopie zu arbeiten (ly:music-deep-copy kann dafür
benützt werden). Der Grund ist eine stille Übereinkunft: musikalische
Funktionen dürfen ihre Argumente verändern: sie werden entweder von
Grund auf erstellt (wie Eingabe des Benutzers) oder sind schon kopiert
(etwa Verweis auf eine Variable mit ‘\Bezeichnung’ oder Noten aus
einem Scheme-Ausdruck ‘$(…)’ sind Kopien). Weil es uneffizient
wäre, unnötige Kopien zu erstellen, wird der Wiedergabewert einer musikalischen
Funktion nicht kopiert. Um sich also an die Übereinkunft zu halten,
dürfen Argumente nicht mehr als einmal benützt werden, und sie wiederzugeben
zählt als eine Benutzung.
In einem früheren Beispiel wurden Noten konstruiert, indem ein musikalisches
Argument wiederholt wurde. In diesem Fall muss wenigstens eine Wiederholung
eine Kopie ihres Arguments sein. Wenn es keine Kopie ist, können seltsame
Dinge passieren. Wenn man beispielsweise \relative oder \transpose
auf die resultierenden Noten anwendet, die die gleichen Elemente mehrmals
enthalten, werden die Elemente mehrmals der \relative-Veränderung
oder Transposition unterworfen. Wenn man sie einer musikalischen Variable
zuweist, wird dieser Fluch aufgehoben, denn der Verweis auf ‘\Bezeichnung’
erstellt wiederum eine Kopie, die nicht die Identität der wiederholten
Elemente überträgt.
Während die Funktion oben keine musikalische Funktion ist, wird sie
normalerweise inmitten musikalischer Funktionen eingesetzt. Darum
ist es sinnvoll, der gleichen Übereinkunft zu folgen, die für musikalische
Funktionen gelten: Die Eingabe kann verändert worden sein, um die
Ausgabe zu produzieren, und der den Aufruf erstellt, ist verantwortlich
für die Erstellung von Kopien, wenn er immernoch die unveränderten
Argumente benötigt. Wenn man sich LilyPonds eigene Funktionen wie etwa
music-map anschaut, sieht man, dass sie denselben Prinzipien folgen.
Aber wo waren wir? Jetzt gibt es ein note-event, das verändert
werden kann, nicht unter Einsatz von ly:music-deep-copy sondern
aufgrund einer langen Erklärung. Der Akzent wird zu seiner
'articulations-Liste hinzugefügt:
(set! place neuer-Wert) |
Was in diesem Fall „gesetzt“ werden soll („place“) ist die
‚’articulations‘-Eigenschaft des note-event-Ausdrucks.
(ly:music-property note-event 'articulations) |
ly:music-property ist die Funktion, mit der musikalische
Eigenschaften erreicht werden können (die 'articulations,
'duration, 'pitch usw., die in der Ausgabe von
\displayMusic weiter oben angezeigt werden). Der neue
Wert ist, was ehemals die 'articulations-Eigenschaft war, mit einem
zusätzlichen Element: dem ArticulationEvent-Ausdruck,
der aus der Ausgabe von \displayMusic kopiert werden kann:
(cons (make-music 'ArticulationEvent
'articulation-type "accent")
(ly:music-property result-event-chord 'articulations))
|
cons wird benutzt, um ein Element vorne an eine Liste hinzuzufügen,
ohne dass die originale Liste verändert wird. Das ist es, was die
Funktion tun soll: die gleiche Liste wie vorher, aber mit dem neuen
ArticulationEvent-Ausdruck. Die Reihenfolge innerhalb
der Elementeeigenschaft ist hier nicht relevant.
Wenn schließlich die Akzent-Artikulation zu der entsprechenden
elements-Eigenschaft hinzugefügt ist, kann
note-event ausgegeben werden, darum die letzte Zeile
der Funktion.
Jetzt wird die add-accent-Funktion in eine musikalische
Funktion umgewandelt (hierzu gehört etwas syntaktischer Zuckerguß und
eine Deklaration des Typs ihres einzigen „wirklichen“ Arguments:
addAccent = #(define-music-function (note-event)
(ly:music?)
"Add an accent ArticulationEvent to the articulations of `note-event',
which is supposed to be a NoteEvent expression."
(set! (ly:music-property note-event 'articulations)
(cons (make-music 'ArticulationEvent
'articulation-type "accent")
(ly:music-property note-event 'articulations)))
note-event)
|
Eine Überprüfung, dass die Funktion richtig arbeitet, geschieht folgendermaßen:
\displayMusic \addAccent c4 |
| [ < ] | [ > ] | [ << ] | [ Nach oben ] | [ >> ] |
Dieses Dokument wurde erzeugt von gub am 13. Juli 2020 durch texi2html 1.82.
Andere Sprachen: English, español, français.
Über die automatische Sprachauswahl.