Extending LilyPond: 1.3.4 Adding articulation to notes (example)

### 1.3.4 Adding articulation to notes (example)

The easy way to add articulation to notes is to merge two music expressions into one context, as explained in Creating contexts. However, suppose that we want to write a music function that does this.

A `$variable` inside the `#{...#}` notation is like a regular `\variable` in classical LilyPond notation. We know that

>     { \music -. -> }

will not work in LilyPond. We could avoid this problem by attaching the articulation to a fake note,

>     { << \music s1*0-.-> }

but for the sake of this example, we will learn how to do this in Scheme. We begin by examining our input and desired output,

>     %  input
>     \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))))
>     =====
>     %  desired output
>     \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))
>             (make-music
>               'ArticulationEvent
>               'articulation-type
>               "marcato")))

We see that a note (`c4`) is represented as an `EventChord` expression, with a `NoteEvent` expression in its elements list. To add a marcato articulation, an `ArticulationEvent` expression must be added to the elements property of the `EventChord` expression.

To build this function, we begin with

>     (define (add-marcato event-chord)
>       "Add a marcato ArticulationEvent to the elements of `event-chord',
>       which is supposed to be an EventChord expression."
>       (let ((result-event-chord (ly:music-deep-copy event-chord)))
>         (set! (ly:music-property result-event-chord 'elements)
>               (cons (make-music 'ArticulationEvent
>                       'articulation-type "marcato")
>                     (ly:music-property result-event-chord 'elements)))
>         result-event-chord))

The first line is the way to define a function in Scheme: the function name is `add-marcato`, and has one variable called `event-chord`. In Scheme, the type of variable is often clear from its name. (this is good practice in other programming languages, too!)

>     "Add a marcato..."

is a description of what the function does. This is not strictly necessary, but just like clear variable names, it is good practice.

>     (let ((result-event-chord (ly:music-deep-copy event-chord)))

`let` is used to declare local variables. Here we use one local variable, named `result-event-chord`, to which we give the value `(ly:music-deep-copy event-chord)`. `ly:music-deep-copy` is a function specific to LilyPond, like all functions prefixed by `ly:`. It is use to make a copy of a music expression. Here we copy `event-chord` (the parameter of the function). Recall that our purpose is to add a marcato to an `EventChord` expression. It is better to not modify the `EventChord` which was given as an argument, because it may be used elsewhere.

Now we have a `result-event-chord`, which is a `NoteEventChord` expression and is a copy of `event-chord`. We add the marcato to its `'elements` list property.

>     (set! place new-value)

Here, what we want to set (the ‘place’) is the `'elements` property of `result-event-chord` expression.

>     (ly:music-property result-event-chord 'elements)

`ly:music-property` is the function used to access music properties (the `'elements`, `'duration`, `'pitch`, etc, that we see in the `\displayMusic` output above). The new value is the former `'elements` property, with an extra item: the `ArticulationEvent` expression, which we copy from the `\displayMusic` output,

>     (cons (make-music 'ArticulationEvent
>             'articulation-type "marcato")
>           (ly:music-property result-event-chord 'elements))

`cons` is used to add an element to a list without modifying the original list. This is what we want: the same list as before, plus the new `ArticulationEvent` expression. The order inside the `'elements` property is not important here.

Finally, once we have added the marcato articulation to its `elements` property, we can return `result-event-chord`, hence the last line of the function.

Now we transform the `add-marcato` function into a music function,

>     addMarcato = #(define-music-function (parser location event-chord)
>                                          (ly:music?)
>         "Add a marcato ArticulationEvent to the elements of `event-chord',
>         which is supposed to be an EventChord expression."
>         (let ((result-event-chord (ly:music-deep-copy event-chord)))
>           (set! (ly:music-property result-event-chord 'elements)
>                 (cons (make-music 'ArticulationEvent
>                         'articulation-type "marcato")
>                       (ly:music-property result-event-chord 'elements)))
>           result-event-chord))

We may verify that this music function works correctly,

>     \displayMusic \addMarcato c4

他の言語: deutsch

#### LilyPond — Extending