[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Racine] [Table des matières] [Index] [ ? ]

1.3 Construction de fonctions complexes

@translationof Building complicated functions

Nous allons voir dans cette partie les moyens dont vous disposez pour obtenir les informations qui vous permettront de créer vos propres fonctions musicales complexes.


[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Racine] [Table des matières] [Index] [ ? ]

1.3.1 Affichage d’expressions musicales

@translationof Displaying music expressions

Lorsque l’on veut écrire une fonction musicale, il est intéressant d’examiner comment une expression musicale est représentée en interne. Vous disposez à cet effet de la fonction musicale \displayMusic.

 
{
  \displayMusic { c'4\f }
}

affichera

 
(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'articulations
          (list (make-music
                  'AbsoluteDynamicEvent
                  'text
                  "f"))
          'duration
          (ly:make-duration 2 0 1/1)
          'pitch
          (ly:make-pitch 0 0 0))))

Par défaut, LilyPond affichera ces messages sur la console, parmi toutes les autres informations. Vous pouvez, afin de les isoler et de garder le résultat des commandes \display{TRUC}, spécifier un port optionnel à utiliser pour la sortie :

 
{
  \displayMusic #(open-output-file "display.txt") { c'4\f }
}

Ceci aura pour effet d’écraser tout fichier précédemment généré. Lorsque plusieurs expressions doivent être retranscrites, il suffit de faire appel à une variable pour le port puis de la réutiliser :

 
{
  port = #(open-output-file "display.txt")
  \displayMusic \port { c'4\f }
  \displayMusic \port { d'4 }
  #(close-output-port port)
}

La documentation de Guile fournit une description détaillée des ports. Clôturer un port n’est requis que si vous désirez consulter le fichier avant que LilyPond n’ait fini, ce dont nous ne nous sommes pas préoccupé dans le premier exemple.

L’information sera encore plus lisible après un peu de mise en forme :

 
(make-music 'SequentialMusic
  'elements (list
	     (make-music 'NoteEvent
               'articulations (list
			       (make-music 'AbsoluteDynamicEvent
				 'text
				 "f"))
	       'duration (ly:make-duration 2 0 1/1)
	       'pitch    (ly:make-pitch 0 0 0))))

Une séquence musicale { … } se voit attribuer le nom de SequentialMusic, et les expressions qu’elle contient sont enregistrées en tant que liste dans sa propriété 'elements. Une note est représentée par un objet NoteEvent – contenant les propriétés de durée et hauteur – ainsi que l’information qui lui est attachée – en l’occurrence un AbsoluteDynamicEvent ayant une propriété text de valeur "f" – et stockée dans sa propriété articulations.

La fonction \displayMusic renvoie la musique qu’elle affiche ; celle-ci sera donc aussi interprétée. L’insertion d’une commande \void avant le \displayMusic permet de s’affranchir de la phase d’interprétation.


[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Racine] [Table des matières] [Index] [ ? ]

1.3.2 Propriétés musicales

@translationof Music properties

Nous abordons ici les propriétés music, et non pas les propriétés context ou layout.

Partons de cet exemple simple :

 
someNote = c'
\displayMusic \someNote
===>
(make-music
  'NoteEvent
  'duration
  (ly:make-duration 2 0 1/1)
  'pitch
  (ly:make-pitch 0 0 0))

L’objet NoteEvent est la représentation brute de someNote. Voyons ce qui se passe lorsque nous plaçons ce c’ dans une construction d’accord :

 
someNote = <c'>
\displayMusic \someNote
===>
(make-music
  'EventChord
  'elements
  (list (make-music
          'NoteEvent
          'duration
          (ly:make-duration 2 0 1/1)
          'pitch
          (ly:make-pitch 0 0 0))))

L’objet NoteEvent est maintenant le premier objet de la propriété 'elements de someNote.

\displayMusic utilise la fonction display-scheme-music pour afficher la représentation en Scheme d’une expression musicale :

 
#(display-scheme-music (first (ly:music-property someNote 'elements)))
===>
(make-music
  'NoteEvent
  'duration
  (ly:make-duration 2 0 1/1)
  'pitch
  (ly:make-pitch 0 0 0))

La hauteur de la note est accessible au travers de la propriété 'pitch de l’objet NoteEvent :

 
#(display-scheme-music
   (ly:music-property (first (ly:music-property someNote 'elements))
                      'pitch))
===>
(ly:make-pitch 0 0 0)

La hauteur de la note se modifie en définissant sa propriété 'pitch :

 
#(set! (ly:music-property (first (ly:music-property someNote 'elements))
                          'pitch)
       (ly:make-pitch 0 1 0)) ;; set the pitch to d'.
\displayLilyMusic \someNote
===>
d'4

[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Racine] [Table des matières] [Index] [ ? ]

1.3.3 Doublement d’une note avec liaison (exemple)

@translationof Doubling a note with slurs (example)

Supposons que nous ayons besoin de créer une fonction transformant une saisie a en { a( a) }. Commençons par examiner comment le résultat est représenté en interne.

 
\displayMusic{ a'( a') }
===>
(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'articulations
          (list (make-music
                  'SlurEvent
                  'span-direction
                  -1))
          'duration
          (ly:make-duration 2 0 1/1)
          'pitch
          (ly:make-pitch 0 5 0))
        (make-music
          'NoteEvent
          'articulations
          (list (make-music
                  'SlurEvent
                  'span-direction
                  1))
          'duration
          (ly:make-duration 2 0 1/1)
          'pitch
          (ly:make-pitch 0 5 0))))

Mauvaise nouvelle ! Les expressions SlurEvent doivent s’ajouter « à l’intérieur » de la note – dans sa propriété articulations.

Examinons à présent la saisie :

 
\displayMusic a'
===>
(make-music
  'NoteEvent
  'duration
  (ly:make-duration 2 0 1/1)
  'pitch
  (ly:make-pitch 0 5 0))))

Nous aurons donc besoin, dans notre fonction, de cloner cette expression – de telle sorte que les deux notes constituent la séquence – puis d’ajouter un SlurEvent à la propriété 'articulations de chacune d’elles, et enfin réaliser un SequentialMusic de ces deux éléments NoteEvent. En tenant compte du fait que, dans le cadre d’un ajout, une propriété non définie est lue '() (une liste vide), aucune vérification n’est requise avant d’introduire un nouvel élément en tête de la propriété articulations.

 
doubleSlur = #(define-music-function (note) (ly:music?)
         "Renvoie : { note ( note ) }.
         `note' est censé être une note unique."
         (let ((note2 (ly:music-deep-copy note)))
           (set! (ly:music-property note 'articulations)
                 (cons (make-music 'SlurEvent 'span-direction -1)
                       (ly:music-property note 'articulations)))
           (set! (ly:music-property note2 'articulations)
                 (cons (make-music 'SlurEvent 'span-direction 1)
                       (ly:music-property note2 'articulations)))
           (make-music 'SequentialMusic 'elements (list note note2))))

[ < ] [ > ]   [ << ] [Plus haut] [ >> ]         [Racine] [Table des matières] [Index] [ ? ]

1.3.4 Ajout d’articulation à des notes (exemple)

@translationof Adding articulation to notes (example)

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

[ < ] [ > ]   [ << ] [Plus haut] [ >> ]

Ce document a été généré le le 13 juillet 2020 par gub en utilisant texi2html 1.82.

Autres langues : English, deutsch, español.
À propos de la sélection automatique de la langue.