A.3.4 Añadir articulaciones a las notas (ejemplo)
La manera fácil de añadir articulación a las notas es mezclar dos expresiones musicales en un solo contexto. Sin embargo, supongamos que queremos escribir una función musical que lo haga. Esto tiene la ventaja adicional de que podemos usar esa función musical para añadir una articulación (como una instrucción de digitación) a una nota única dentro de un acorde, lo cual no es posible si nos limitamos a mezclar fragmentos de música independientes.
Una $variable
dentro de la notación #{…#}
es como
una \variable
normal en la notación clásica de LilyPond.
Sabemos que
{ \music -. -> }
no funciona en LilyPond. Podríamos evitar este problema adjuntando la articulación a un acorde vacío,
{ << \music <> -. -> >> }
pero a los efectos de este ejemplo, aprenderemos ahora cómo hacerlo en Scheme. Empezamos examinando nuestra entrada y la salida deseada,
% input \displayMusic c4 ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1/1) 'pitch (ly:make-pitch -1 0 0)))) ===== % desired output \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))
Vemos que una nota (c4
) se representa como una expresión
NoteEvent
. Para añadir una articulación de acento, se debe
añadir una expresión ArticulationEvent
a la propiedad
articulations
de la expresión NoteEvent
.
Para construir esta función, empezamos con
(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)
La primera línea es la forma de definir una función en Scheme: el
nombre de la función es add-accent
, y tiene una variable
llamada note-event
. En Scheme, el tipo de variable suele
quedar claro a partir de su nombre (¡esto también es una buena
práctica en otros lenguajes de programación!)
"Add an accent…"
es una descripción de lo que hace la función. No es estrictamente necesaria, pero de igual forma que los nombres claros de variable, es una buena práctica.
Se preguntará porqué modificamos el evento de nota directamente en
lugar de trabajar sobre una copia (se puede usar
ly:music-deep-copy
para ello). La razón es un contrato
silencioso: se permite que las funciones musicales modifiquen sus
argumentos; o bien se generan partiendo de cero (como la entrada del
usuario) o están ya copiadas (referenciar una variable de música con
‘\name’ o la música procedente de expresiones de Scheme
inmediatas ‘$(…)’ proporcionan una copia). Dado que sería
ineficiente crear copias innecesarias, el valor devuelto de una
función musical no se copia. Así pues, para cumplir dicho
contrato, no debemos usar ningún argumento más de una vez, y
devolverlo cuenta como una vez.
En un ejemplo anterior, hemos construido música mediante la repetición
de un argumento musical dado. En tal caso, al menos una repetidión
tuvo que ser una copia de sí misma. Si no lo fuese, podrían ocurrir
cosas muy extrañas. Por ejemplo, si usamos \relative
o
\transpose
sobre la música resultante que contiene los mismos
elementos varias veces, estarían sujetos varias veces a la
relativización o al transporte. Si los asignamos a una variable de
música, se rompe el curso porque hacer referencia a ‘\name’
creará de nuevo una copia que no retiene la identidad de los elementos
repetidos.
Ahora bien, aun cuando la función anterior no es una función musical,
se usará normalmente dentro de funciones musicales. Así pues, tiene
sentido obedecer el mismo convenio que usamos para las funciones
musicales: la entrada puede modificarse para producir la salida, y el
código que llama es responsable de crear las copias si aún necesita el
propio argumento sin modificar. Si observamos las propias funciones
de LilyPond como music-map
, veremos que se atienen a los mismos
principios.
¿En qué punto nos encontramos? Ahora tenemos un note-event
que
podemos modificar, no a causa de la utilización de
ly:music-deep-copy
sino por una explicación muy desarrollada.
Añadimos el acento a su propiedad de lista 'articulations
.
(set! place new-value)
Aquí, lo que queremos establecer (el ‘place’) es la propiedad
'articulations
de la expresión note-event
.
(ly:music-property note-event 'articulations)
ly:music-property
es la función ustilizada para acceder a las
propiedades musicales (las 'articulations
, 'duration
,
'pitch
, etc, que vemos arriba en la salida de
\displayMusic
). El nuevo valor es la antigua propiedad
'articulations
, con un elemento adicional: la expresión
ArticulationEvent
, que copiamos a partir de la salida de
\displayMusic
,
(cons (make-music 'ArticulationEvent 'articulation-type "accent") (ly:music-property result-event-chord 'articulations))
Se usa cons
para añadir un elemento a la parte delantera de una
lista sin modificar la lista original. Esto es lo que queremos: la
misma lista de antes, más la nueva expresión ArticulationEvent
.
El orden dentro de la propiedad 'articulations
no tiene
importancia aquí.
Finalmente, una vez hemos añadido la articulación de acento a su
propiedad articulations
, podemos devolver note-event
, de
aquí la última línea de la función.
Ahora transformamos la función add-accent
en una función
musical (es cuestión de un poco de aderezo sintáctico y una
declaración del tipo de su único argumento ‘real’).
addAccent = #(define-music-function (parser location 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)
Podemos verificar que esta función musical funciona correctamente:
\displayMusic \addAccent c4
Otros idiomas: English, deutsch, français.
Acerca de la selección automática del idioma.