[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

1.3 Komplizierte Funktionen erstellen

@translationof Building complicated functions

Dieser Abschnitt zeigt, wie man Information zusammensucht, um komplizierte musikalische Funktionen zu erstellen.


[ < ] [ > ]   [ << ] [ Nach oben ] [ >> ]         [Anfang] [Inhalt] [Index] [ ? ]

1.3.1 Musikalische Funktionen darstellen

@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] [ ? ]

1.3.2 Eigenschaften von Musikobjekten

@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] [ ? ]

1.3.3 Verdoppelung einer Note mit Bindebögen (Beispiel)

@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] [ ? ]

1.3.4 Artikulationszeichen zu Noten hinzufügen (Beispiel)

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