1.3.4 Ajout d’articulation à des notes (exemple)
Le moyen d’ajouter une articulation à des notes consiste à juxtaposer deux expressions musicales. L’option de réaliser nous-mêmes une fonction musicale à cette fin.
Un $variable
au milieu de la notation #{ … #}
se
comporte exactement comme un banal \variable
en notation LilyPond
traditionnelle. Nous pourrions écrire
{ \musique -. -> }
mais, pour les besoins de la démonstration, nous allons voir comment réaliser ceci en Scheme. Commençons par examiner une saisie simple et le résultat auquel nous désirons aboutir :
% saisie \displayMusic c4 ===> (make-music 'NoteEvent 'duration (ly:make-duration 2 0 1/1) 'pitch (ly:make-pitch -1 0 0)))) ===== % résultat attendu \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))
Nous voyons qu’une note (c4
) est représentée par une expression
NoteEvent
. Si nous souhaitons ajouter une articulation
accent, nous devrons ajouter une expression
ArticulationEvent
à la propriété articulations
de
l’expression NoteEvent
.
Construisons notre fonction en commençant par
(define (ajoute-accent note-event) "Ajoute un accent (ArticulationEvent) aux articulations de `note-event', qui est censé être une expression NoteEvent." (set! (ly:music-property note-event 'articulations) (cons (make-music 'ArticulationEvent 'articulation-type 'accent) (ly:music-property note-event 'articulations))) note-event)
La première ligne est la manière de définir une fonction en Scheme : la
fonction Scheme a pour nom ajoute-accent
et elle comporte une
variable appelée note-event
. En Scheme, le type d’une variable
se déduit la plupart de temps de par son nom – c’est d’ailleurs une
excellente pratique que l’on retrouve dans de nombreux autres langages.
"Ajoute un accent…"
décrit ce que fait la fonction. Bien que ceci ne soit pas primordial, tout comme des noms de variable évidents, tâchons néanmoins de prendre de bonnes habitudes dès nos premiers pas.
Vous pouvez vous demander pourquoi nous modifions directement
l’événement note plutôt que d’en manipuler une copie – on pourrait
utiliser ly:music-deep-copy
à cette fin. La raison en est qu’il
existe un contrat tacite : les fonctions musicales sont autorisées
à modifier leurs arguments – ils sont générés en partant de zéro (comme
les notes que vous saisissez) ou déjà recopiés (faire référence à une
variable musicale avec ‘\nom’ ou à de la musique issue
d’expressions Scheme ‘$(…)’ aboutit à une copie). Dans la
mesure où surmultiplier les copies serait contre productif, la valeur de
retour d’une fonction musicale n’est pas recopiée. Afin de
respecter ce contrat, n’utilisez pas un même argument à plusieurs
reprises, et n’oubliez pas que le retourner compte pour une utilisation.
Dans un exemple précédent, nous avons construit de la musique en
répétant un certain argument musical. Dans ce cas là, l’une des
répétitions se devait d’être une copie. Dans le cas contraire,
certaines bizarreries auraient pu survenir. Par exemple, la présence
d’un \relative
ou d’un \transpose
, après plusieurs
répétitions du même élément, entraînerait des « relativisations » ou
transpositions en cascade. Si nous les assignons à une variable
musicale, l’enchaînement est rompu puisque la référence à ‘\nom’
créera une nouvelle copie sans toutefois prendre en considération
l’identité des éléments répétés.
Cette fonction n’étant pas une fonction musicale à part entière, elle
peut s’utiliser dans d’autres fonctions musicales. Il est donc sensé de
respecter le même contrat que pour les fonctions musicales :
l’entrée peut être modifiée pour arriver à une sortie, et il est de la
responsabilité de l’appelant d’effectuer des copies s’il a réellement
besoin de l’argument dans son état originel. Vous constaterez, à la
lecture des fonctions propres à LilyPond, comme music-map
, que ce
principe est toujours respecté.
Revenons à nos moutons… Nous disposons maintenant d’un note-event
que nous pouvons modifier, non pas grâce à un ly:music-deep-copy
,
mais plutôt en raison de notre précédente réflexion. Nous ajoutons
l’accent à la liste de ses propriétés 'articulations
.
(set! emplacement nouvelle-valeur)
L’emplacement est ce que nous voulons ici définir. Il s’agit de la
propriété 'articulations
de l’expression note-event
.
(ly:music-property note-event 'articulations)
La fonction ly:music-property
permet d’accéder aux propriétés
musicales – les 'articulations
, 'duration
,
'pitch
, etc. que \displayMusic
nous a indiquées. La
nouvelle valeur sera l’ancienne propriété 'articulations
,
augmentée d’un élément : l’expression ArticulationEvent
, que nous
recopions à partir des informations de \displayMusic
.
(cons (make-music 'ArticulationEvent 'articulation-type 'accent) (ly:music-property result-event-chord 'articulations))
cons
permet d’ajouter un élément en tête de liste sans pour
autant modifier la liste originale. C’est exactement ce que nous
recherchons : la même liste qu’auparavant, plus la nouvelle
expression ArticulationEvent
. L’ordre au sein de la propriété
'articulations
n’a ici aucune importance.
Enfin, après avoir ajouté l’articulation accent à sa
propriété articulations
, nous pouvons renvoyer le
note-event
, ce que réalise la dernière ligne de notre fonction.
Nous pouvons à présent transformer la fonction ajoute-accent
en
fonction musicale, à l’aide d’un peu d’enrobage syntaxique et mention du
type de son argument.
ajouteAccent = #(define-music-function (note-event) (ly:music?) "Ajoute un accent (ArticulationEvent) aux articulations de `note-event', qui est censé être une expression NoteEvent." (set! (ly:music-property note-event 'articulations) (cons (make-music 'ArticulationEvent 'articulation-type 'accent) (ly:music-property note-event 'articulations))) note-event)
Par acquis de conscience, vérifions que tout ceci fonctione :
\displayMusic \ajouteAccent c4