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