A.3.4 Afegir articulacions a les notes (exemple)

La manera fàcil d’afegir una articulació a les notes és juxtaposar dos expressions musicals. Malgrat això, suposem que volem escriure una funció musical que ho faci.

Una $variable dins de la notació #{…#} és com una \variable normal en la notació clàssica del LilyPond. Podríem escriure

{ \music -. -> }

però als efectes d’aquest exemple, aprendrem ara com fer-lo a l’Scheme. Comencem examinant la nostra entrada i la sortida desitjada.

%  input
\displayMusic c4
===>
(make-music
  'NoteEvent
  'duration
  (ly:make-duration 2 0 1/1)
  'pitch
  (ly:make-pitch -1 0 0))))
=====
%  sortida desitjada
\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))

Veiem que una nota (c4) es representa como una expressió NoteEvent. Per afegir una articulació d’accent, s’ha d’afegir una expressió ArticulationEvent a la propietat articulations de l’expressió NoteEvent.

Per construir aquesta funció, comencem amb

(define (add-accent note-event)
  "Afegeix un accent ArticulationEvent a les articulacions de `note-event',
  que se suposa que és una expressió NoteEvent."
  (set! (ly:music-property note-event 'articulations)
        (cons (make-music 'ArticulationEvent
                'articulation-type 'accent)
              (ly:music-property note-event 'articulations)))
  note-event)

La primera línea és la forma de definir una funció a l’Scheme: el nom de la funció és add-accent, i té una variable anomenada note-event. A l’Scheme, el tipus de variable sol quedar clar a partir del seu nom (això també es una bona pràctica a d’altres llenguatges de programació).

"Afegeix un accent…"

és una descripció del que fa la funció. No és estrictament necessari, però d’igual forma que els noms clars de variable, és una bona pràctica.

Us preguntareu perquè modifiquem l’esdeveniment de nota directament enlloc de treballar sobre una còpia (es pot usar ly:music-deep-copy per això). La raó és un contracte silenciós: es permet que les funcions musicals modifiquin els seus arguments; o bé es generen partint de zero (com l’entrada de l’usuari) o estan ja copiades (referenciar una variable de música com ‘\name’ o la música procedent d’expressions de l’Scheme immediates ‘$(…)’ proporcionen una còpia). Donat que seria ineficient crear còpies innecessàries, el valor retornat d’una funció musical no es copia. Així doncs, per complir aquest contracte, no hem d’usar cap argument més d’un cop, i retornar-lo compta com un cop.

A un exemple anterior, hem construït música mitjançant la repetició d’un argument musical donat. En aquest cas, almenys una repetició ha d’haver sigut una còpia de sí mateixa. Si no ho fos, podrien ocórrer coses molt estranyes. Per exemple, si usem \relative o \transpose sobre la música resultant que conté els mateixos elements diverses vegades, estarien subjectes diverses vegades a la relativització o al transport. Si els assignem a una variable de música, es trenca el curs perquè fer referència a ‘\name’ crearà de nou una còpia que no reté la identitat dels elements repetits.

Ara bé, tot i que la funció anterior no és una funció musical, s’usarà normalment dins de funcions musicals. Així doncs, té sentit obeir el mateix conveni que usem per a les funcions musicals: l’entrada pot modificar-se per produir la sortida, i el codi que crida és responsable de crear les còpies si encara li cal el propi argument sense modificar. Si observem les pròpies funcions del LilyPond com music-map, veurem que respecten els mateixos principis.

En quin punt ens trobem? Ara tenim un note-event que podem modificar, no a causa de la utilització de ly:music-deep-copy sinó per una explicació molt desenvolupada. Afegim l’accent a la seva propietat de llista 'articulations.

(set! place new-value)

Aquí el que volem establir (el ‘place’) és la propietat 'articulations de l’expressió note-event.

(ly:music-property note-event 'articulations)

ly:music-property és la funció utilitzada per accedir a les propietats musicals (les 'articulations, 'duration, 'pitch, etc, que veiem a dalt a la sortida de \displayMusic). EL nou valor de la propietat 'articulations, amb un element addicional: l’expressió ArticulationEvent, que copiem a partir de la sortida de \displayMusic,

(cons (make-music 'ArticulationEvent
        'articulation-type 'accent)
      (ly:music-property result-event-chord 'articulations))

S’usa cons per afegir un element a la part d’endavant d’una llista sense modificar la llista original. Això és el que volem: la mateixa llista d’abans, més nova expressió ArticulationEvent. L’ordre de la propietat 'articulations no té importància aquí.

Finalment, un cop hem afegit l’articulació d’accent a la seva propietat articulations, podem retornar note-event, per això l’última línea de la funció.

Ara transformem la funció add-accent en una funció musical (és qüestió d’una mica d’ajustament sintàctic i una declaració del tipus de argument).

addAccent = #(define-music-function (note-event)
                                     (ly:music?)
  "Afegir un accent ArticulationEvent a les articulacions de `note-event',
  que se suposa que és una expressió NoteEvent."
  (set! (ly:music-property note-event 'articulations)
        (cons (make-music 'ArticulationEvent
                'articulation-type 'accent)
              (ly:music-property note-event 'articulations)))
  note-event)

A continuació verifiquem que aquesta funció musical funciona correctament:

\displayMusic \addAccent c4

Extender LilyPond v2.25.32 (development-branch).