Expressions musicales#

La première étape de la compilation d’un fichier LilyPond est l’analyse syntaxique, qui produit des expressions musicales et exécute sur eux des fonctions musicales.

Définition de fonctions musicales#

Les fonctions musicales constituent l’outil fondamental pour créer ou modifier des expressions musicales. Voici un modèle pour écrire une fonction musicale :

maFonction =
#(define-music-function (argument1 argument2 ...) (type1? type2? ...)
   corps de la fonction ...)

Ce code définit une fonction que l’on peut appeler avec \maFonction. Les arguments argument1, argument2, …, doivent respectivement satisfaire aux prédicats type1?, type2?, … Le corps de la fonction est une suite d’expressions Scheme. Comme dans n’importe quelle fonction Scheme normale, ces expressions sont évaluées dans l’ordre et la valeur de la dernière expression devient la valeur renvoyée par la fonction. Voici une fonction musicale simple :

\version "2.25.8"

withNoteNames =
#(define-music-function (music) (ly:music?)
   #{
     <<
       \new Voice $music
       \new NoteNames $music
     >>
   #})

\withNoteNames \relative c' { c d e c e f g e }
Résultat../../images/b383c7e78c2e4a4d73d51e0b96c8e37a9d35a9c966530ca10ea23cfc43bfe4ff.svg

Typage des arguments#

LilyPond vérifie que chaque argument d’une fonction est du bon type. Étant donné que Scheme est un langage au typage dit latent, où on ne peut pas demander le type d’une valeur mais seulement demander si une valeur est d’un certain type, les types des arguments sont donnés sous forme de prédicats.

\version "2.25.8"

nrepeats =
#(define-music-function (n music) (index? ly:music?)
   #{ \repeat unfold #n { #music } #})

\nrepeats 4 aes
Résultat../../images/9f13463f918497ed9764545be8a617894c7e37295df7493d36a2e511638c6ed7.svg

La fonction ci-dessus est un raccourci (certes plutôt inutile) pour \repeat unfold .... Elle prend deux arguments, n et music. n doit être un entier et music doit être une expression musicale. Lorsque la fonction est appelée, LilyPond exécute automatiquement les vérifications (index? n) et (ly:music? music).

Considérons maintenant un deuxième exemple :

\version "2.25.8"

keyDuring =
#(define-music-function (duration pitch) (ly:duration? ly:pitch?)
   #{ \key #pitch \major s $duration \key c \major #})

\new Staff <<
  { c'4 c' c' c' }
  { s2 \keyDuring 4 aes s4 }
>>
Résultat../../images/9cc50beacfe6b198a54202f312fc51e4f74ec13e08c0667571716640d369c109.svg

Cette fonction \keyDuring prend deux arguments. Elle renvoie une expression musicale où des silences invisibles sont ajoutés pour que l’armure donnée soit active pendant la durée donnée, après quoi l’armure revient à do majeur.

Voici comment nous avons appelé chacune de nos fonctions :

\nrepeats 4 aes
\keyDuring 4 aes

Bien que les arguments soient exactement les mêmes, ils ont été interprétés différemment. \nrepeats a reçu un entier et une expression musicale, alors que \keyDuring a reçu une durée et une hauteur ! Cette magie est permis par l’analyseur syntaxique, qui s’appuie sur les prédicats. Lorsque les jetons 4 et aes sont lus, l’analyseur syntaxique essaie différentes interprétations, jusqu’à en trouver une qui satisfasse au prédicat.

Le manuel de notation de LilyPond contient une liste des prédicats de type prédéfinis. Un tableau résumant les principaux se trouve dans Introduction aux fonctions musicales.

Arguments facultatifs#

Si le prédicat d’un argument est mis entre parenthèses, cet argument est considéré comme facultatif. Lorsque la fonction est appelée et cet argument n’est pas passé, il prend la valeur #f. Voici une fonction qui affiche une indication de tempo avec l’une des valeurs les plus courantes, donnée sous la forme d’un terme musical comme « Allegro » ou « Andante ». Le texte à afficher est facultatif, le terme lui-même étant utilisé s’il n’est pas passé.

\version "2.25.8"

tempi =
#'(("Largo" . 50)
   ("Lento" . 60)
   ("Adagio" . 70)
   ("Andante" . 90)
   ("Moderato" . 100)
   ("Allegro" . 140)
   ("Presto" . 170))


commonTempo =
#(define-music-function (printed-term duration term) ((markup?) ly:duration? string?)
   #{
     \tempo $(or printed-term term) $duration = $(assoc-ref tempi term)
   #})


\relative c' {
  \commonTempo 4 Adagio
  c8 d e4 d c
  \commonTempo "Allegro con brio" 4 Allegro
  g'4 e'2 g,4
}
Résultat../../images/b75b71fed94d841893ade0deafd9517ee84fa962bf8398a22d5c16611874fe83.svg

On peut changer la valeur par défaut passée lorsque l’argument n’est pas fourni, en mettant une autre valeur dans les parenthèses.

\version "2.25.8"

backgroundCluster =
#(define-music-function (grey-level music) ((number? 0.5) ly:music?)
   #{
     <<
       $music
       {
         \once \override ClusterSpanner.layer = 0
         \once \override ClusterSpanner.color = #(rgb-color grey-level grey-level grey-level)
         \makeClusters $music
       }
     >>
   #})

\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> }
\new Voice \backgroundCluster 0.3 { <g' b''>2 <c''' g'''> }
Résultat../../images/59db711e6b79b769f96bb2d2a22f3a74363750c818d022dd6537b35f7ca2e01a.svg

Bien que les arguments facultatifs soient parfois utiles, ils comportent leur lot de limitations.

Lorsque l’analyseur syntaxique attend un argument facultatif d’une fonction, il prend l’élément suivant dans le fichier, et teste le prédicat de l’argument sur cet élément. Si le prédicat renvoie une valeur vraie (tout sauf #f), l’élément est interprété comme la valeur de l’argument facultatif et l’analyse syntaxique continue avec l’argument suivant. Si, au contraire, le prédicat renvoie #f, alors l’argument prend sa valeur par défaut et l’élément est conservé pour l’argument suivant. Notez bien qu’un élément qui n’a pas satisfait au prédicat doit absolument être utilisé pour un autre argument de la même fonction, et pas pour quelque chose d’autre qui suit l’appel de la fonction. Si cela semble compliqué, le point à retenir en pratique est qu’un argument facultatif n’est réellement facultatif que s’il est suivi d’un argument obligatoire, mais pas si c’est le dernier argument. Échangeons les arguments de notre fonction \backgroundCluster :

\version "2.25.8"

backgroundCluster =
#(define-music-function (music grey-level) (ly:music? (number? 0.5))
   #{
     <<
       $music
       {
         \once \override ClusterSpanner.layer = 0
         \once \override ClusterSpanner.color = #(rgb-color grey-level grey-level grey-level)
         \makeClusters $music
       }
     >>
   #})

\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } 0.3
% \new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } % Does not work
\new Voice \backgroundCluster { <g' b''>2 <c''' g'''> } \default % Works
Résultat../../images/b06df4f0e089ae06d77a4d4fe90d8e100e4e9cf6475c69d1ea53a5a8379e58b4.svg

La dernière ligne de cet exemple montre une possibilité pour appeler tout de même cette fonction qui a ici un argument facultatif en dernier : on ne peut pas omettre cet argument, mais on peut mettre \default pour demander explicitement la valeur par défaut.

Voyons également une autre limitation sur l’exemple de la fonction \commonTempo plus haut, en échangeant les arguments duration et term.

tempi =
#'(("Largo" . 50)
   ("Lento" . 60)
   ("Adagio" . 70)
   ("Andante" . 90)
   ("Moderato" . 100)
   ("Allegro" . 140)
   ("Presto" . 170))


commonTempo =
#(define-music-function (printed-term term duration) ((markup?) string? ly:duration?)
   #{
     \tempo $(or printed-term term) $duration = $(assoc-ref tempi term)
   #})


\relative c' {
  \commonTempo Adagio 4 % Error
  c8 d e4 d c
}

En tant qu’humain, nous comprenons que dans le code \commonTempo Adagio 4, la fonction \commonTempo reçoit deux arguments, et étant donné qu’elle prend trois arguments dont un facultatif, l’argument facultatif doit recevoir sa valeur par défaut. Ce n’est pourtant pas ce qui se produit. Pour comprendre, il faut se mettre à la place de l’analyseur syntaxique. Il essaie d’abord de savoir si Adagio est une valeur valable pour le premier argument, de type markup?. Comme c’est le cas ("Adagio" est une chaîne de caractères, donc un cas particulier de markup), cette valeur est comprise comme le premier argument. La valeur 4 qui la suit est prise pour le deuxième argument, et est rejetée car cet argument attend une valeur string?. Pour résumer, lorsqu’un argument facultatif est suivi d’un argument obligatoire, les valeurs attendues pour l’argument obligatoire ne doivent pas satisfaire au prédicat de l’argument facultatif.

Pour finir, un mot sur les arguments facultatifs multiples : lorsque plusieurs arguments facultatifs se suivent, et que l’un est omis, tous les suivants doivent être omis aussi.

Tout ceci étant dit, les arguments facultatifs restent très utiles, et de nombreuses fonctions prédéfinies par LilyPond les utilisent (exemples : \relative { ... } ou \relative c' { ... }, \time 9/8 ou \time 2,2,2,3 9/8). Cependant, on peut avoir besoin de réfléchir un peu pour trouver une manière d’écrire une fonction qui ne souffre pas des restrictions des arguments facultatifs. Si vous avez du mal avec cela, une bonne stratégie est souvent de séparer la fonction en plusieurs fonctions. Par exemple, au lieu de mettre un \override dans le résultat de la fonction si un argument facultatif est donné, enlever cet argument facultatif, et écrire une deuxième fonction qui fait le \override.

Autres types de fonctions#

Comme leur nom l’indique, les fonctions musicales doivent renvoyer des expressions musicales. Il existe d’autres types de fonctions, dont le type de retour a des contraintes différentes.

Type de fonction

Macro pour définir la fonction

Type de retour

Fonction musicale

define-music-function

Expression musicale (ly:music?)

Fonction événementielle

define-event-function

Post-événement (ly:event?)

Fonction à retour arbitraire

define-scheme-function

N’importe quelle valeur (scheme?)

Fonction sans retour

define-void-function

N’importe quelle valeur, et cette valeur est ignorée

TODO : exemple

Le raccourci \etc#

\etc est un petit mot-clé magique très pratique pour écrire certains types de fonctions. Le principe est que \etc peut remplacer le dernier argument d’une fonction, ou un groupe d’arguments à la fin des arguments qu’attend la fonctions. Alors, au lieu d’exécuter la fonction, le résultat est une nouvelle fonction qui attend les arguments dont \etc a pris la place. Un exemple rendra ce principe plus facile à comprendre :

\version "2.25.8"

makeClarinetPart = \compressMMRests \transpose bes c' \etc

\makeClarinetPart { c' d' e' }
Résultat../../images/dad225c4d83f9333ce339565a48c8a7bf1f41a53377566d9a7323573b741d067.svg

\etc fonctionne également dans certains autres contextes :

\version "2.25.8"

padText = \once \override TextScript.padding = \etc

{ \padText 1.8 c'4^"piu mosso" }
Résultat../../images/2136c03e0c36634d09fa82e217dab9b18622ac6179487a52ef9af204d43d65aa.svg
\version "2.25.8"

\markup reddish = \markup \with-color "LightCoral" \etc

\markup \reddish "Hello"
Résultat../../images/c5a7258e1473be0169b623edd28f5c5877605c7d669bc515ecd8056de01d0f40.svg

Expressions musicales#

Dans les exemples vus jusqu’ici, les paramètres de la fonction musicale étaient simplement utilisés pour construire une expression musicale à l’aide de syntaxe LilyPond avec #{ ... #}. Les fonctions musicales sont toutefois beaucoup plus puissantes – pensez par exemple à \transpose. Elle permettent d’analyser les expressions musicales et d’en construire en Scheme.

Le moyen le plus simple de comprendre comment telle ou telle expression musicale est faite est d’appeler dessus la fonctions musicale \displayMusic, ou bien (ce qui est équivalent) la fonction Scheme display-scheme-music. Ces fonctions tentent d’afficher l’expression musicale sous la forme d’un code Scheme qui pourrait construire cette expression. Prenons un premier exemple.

\version "2.25.8"

\displayMusic { c' d'-> }
Résultat../../images/704978902f15234c5d689dd7c95a47e1c981b2b27a2268c12c9ea79601d66a7d.svg

Ceci affiche dans la console :

(make-music
  'SequentialMusic
  'elements
  (list (make-music
          'NoteEvent
          'pitch
          (ly:make-pitch 0 0)
          'duration
          (ly:make-duration 2))
        (make-music
          'NoteEvent
          'articulations
          (list (make-music
                  'ArticulationEvent
                  'midi-extra-velocity
                  20
                  'articulation-type
                  "accent"))
          'duration
          (ly:make-duration 2)
          'pitch
          (ly:make-pitch 0 1))))

Une expression musicale a un type, pour lequel possibilités sont listées dans la Référence des Propriétés Internes, section Music expressions. Elle possède aussi des propriétés qui la décrivent. Par exemple, une expression NoteEvent a généralement une propriété pitch qui donne sa hauteur et une propriété duration qui donne sa durée, et peut aussi contenir des articulations dans sa propriété articulations. Il est tout à fait possible de lire ou écrire n’importe quelle propriété sur n’importe quelle expression musicale, mais chaque type d’expression a par convention des propriétés qui le décrivent. La plupart du temps, on s’en tient à modifier les propriétés que vont lire les fonctions prédéfinies de LilyPond.

De plus, les types d’expressions musicales sont regroupés dans des classes musicales. Celles-ci sont utilisées pour regrouper des types d’événements qui doivent être traités de façon similaire. Les classes sont listées dans la section Music classes de la référence des propriétés internes.

Les types d’expressions musicales sont par convention écrits en CamelCase, les classes musicales en minuscules-avec-tirets.

(music-is-of-type? music class)

Teste si le type de music fait partie de la classe musicale class.

Propriétés des expressions musicales#

On peut programmer des choses intéressantes en accédant aux propriétés des expressions musicales ou en les modifiant. Les fonctions pour le faire sont ly:music-property et ly:music-set-property!. Voir Probs pour plus de détails.

Certaines expressions musicales contiennent d’autres expressions musicales. En général, c’est dans l’une de ces propriétés :

  • elements, une liste d’expressions musicales, dans SequentialMusic, SimultaneousMusic et divers autres types,

  • articulations, également une liste, pour tous les post-événements rattachés à une note ou un silence.

  • element, une expression musicale simple (pas une liste d’expressions musicales), utilisé pour les expressions musicales qui ne peuvent contenir qu’une seule expression. Par exemple, RelativeOctaveMusic contient pour element l’expression musicale où les octaves ont été rendues relatives.

La propriété name d’une expression musicale donne son type sous forme d’un symbole (comme NoteEvent). Cependant, il est préférable en général de se fonder sur les classes musicales plutôt que de reconnaître des types directement.

Construction d’expressions musicales#

On peut construire des expressions musicales en Scheme, ce qui permet d’ajouter des articulations, de créer des compositions algorithmiques, etc.

(make-music name property1 value1 property2 value2 ...)

Crée une expression musicale.

name est le type de l’expression, un symbole. Les arguments restants vont par deux : le nom d’une propriété (un symbole), et sa valeur.

Si un symbole apparaît plusieurs fois, c’est la dernière qui a la priorité.

On peut aussi, au lieu d’une propriété suivie d’une valeur, mettre une expression musicale. Dans ce cas, toutes les propriétés de cette expression sont copiées. On peut mettre, après cette expression, des propriétés et valeurs qui auront priorité sur les propriétés de l’expression. Par exemple, voici comment changer un NoteEvent en ClusterNoteEvent tout en gardant les mêmes propriétés :

(make-music 'ClusterNoteEvent
            some-note-event)

Transformation d’expressions musicales#

Les expressions musicales contiennent très souvent d’autres expressions musicales imbriquées, qui elles-mêmes contiennent … Très souvent, on ne connaît pas la profondeur de ces imbrications. Par exemple, on pourrait, dans une expression musicale, trouver un NoteEvent à n’importe quelle profondeur dans un SequentialMusic, RelativeOctaveMusic, SimultaneousMusic, etc.

Les outils décrits ici permettent d’agir de manière récursive sur les expressions musicales.

(music-map function music)

Parcourt l’expression musicale, en commençant par appliquer function aux expressions musicales les plus profondes (celles qui ne contiennent pas elles-mêmes d’expressions musicales). Ces expressions musicales sont remplacées dans leur parent par le résultat de function. Puis function est appliquée aux parents, et ainsi de suite. Le résultat de function sur l’expression musicale entière est renvoyé.

Pour des raisons d’efficacité, music-map fonctionne de manière destructive, c’est à dire qu’elle modifie l’expression musicale de départ. C’est pourquoi il est parfois nécessaire de copier des expressions musicales.

Voici un exemple où toutes les répétitions sont changées en des répétitions en pourcents. Les types d’expressions musicales qui représentent une répétition sont regroupés dans la classe musicale repeated-music.

\version "2.25.8"

percentRepeats =
#(define-music-function (music) (ly:music?)
   (music-map
     (lambda (m)
       (if (music-is-of-type? m 'repeated-music)
           (make-music 'PercentRepeatedMusic
                       m)
           m))
     music))

notes =
\relative {
  \clef bass
  \repeat unfold 2 <<
    { s4 <g a c ees> s <gis b d f> s <a c ees g> s <gis b d f> }
    \\
    { c, s g s c s g s }
  >>
}

{ \notes }
\percentRepeats \notes
Résultat../../images/b2e94acb8737efafda8fafa97a936a61b1afaac0b4382514c0f6940f8a9f0303.svg
(music-filter predicate music)

Supprime toutes les expressions à l’intérieur de music qui ne satisfont pas au prédicat predicate.

(for-some-music function music)

Cette fonction est semblable à music-map, mais la fonction est d’abord appliquée à l’expression musicale entière, puis aux expressions qu’elles contient, etc., au lieu de partir des expressions les plus profondes. De plus, for-some-music ne renvoie pas le résultat. function ne renvoie pas une nouvelle expression musicale, mais modifie celle qu’elle prend en argument. for-some-music est généralement utile pour modifier les propriétés d’une expression musicale existante, tandis que music-map est plus utile lorsqu’il faut construire de nouvelles expressions musicales.

Les expressions musicales contenues dans une expression donnée ne sont examinées que si la fonction renvoie #f sur cette expression. Ainsi, on peut penser le résultat de function comme « Faut-il s’arrêter ici (ou bien continuer sur les sous-expressions musicales) ? ».

Voici un exemple simple, qui ajoute une articulation sur toutes les notes. La fonction passée à for-some-music renvoie #t lorsqu’elle rencontre un accord, pour éviter de dupliquer l’articulation.

\version "2.25.8"

addStaccato =
#(define-music-function (music) (ly:music?)
   (for-some-music
     (lambda (m)
       (if (or (music-is-of-type? m 'note-event)
               (music-is-of-type? m 'event-chord))
           (begin
             (ly:music-set-property!
               m
               'articulations
               (cons
                 (make-music 'ArticulationEvent 'articulation-type 'staccato)
                 (ly:music-property m 'articulations)))
             #t)
           #f))
     music)
   music)


\addStaccato { c' d' <e' f'> }
Résultat../../images/f7e1a0cabdf0c7f5fc1f48148f992dc3bde58770399a76bb66ffcdae30638e4d.svg
(map-some-music function music)

Comme for-some-music, mais si le résultat de la fonction n’est pas une expression musicale, il est supprimé de la propriété elements ou articulations de l’expression parente, ce qui permet de filtrer les sous-expressions musicales.

Copier une expression musicale#

Étant donné que la fonction music-map et ses consœurs peuvent muter l’expression musicale qu’elles reçoivent, il peut être nécessaire de copier une expression musicale afin de pouvoir la réutiliser à plusieurs endroits.

(ly:music-deep-copy music)

Renvoie une copie profonde de music.

Hauteurs#

Les hauteurs de note sont la base de la saisie d’une partition. On en trouve dans tout NoteEvent ainsi que dans tout KeyChangeEvent. Il n’est pas rare de programmer avec des hauteurs dans une fonction musicale.

La manière la plus commune d’entrer une hauteur est de l’écrire dans la langue choisie pour les noms des notes avec \language. Cette méthode fonctionne aussi pour définir des variables, ainsi que dans #{ ... #}.

\version "2.25.8"

myPitch = ces
\transpose c \myPitch { c' e' g' c'' }

$(let ((my-other-pitch #{ bes, #}))
  #{ \transpose c #my-other-pitch { c' e' g' c'' } #})
Résultat../../images/8b0d7e81d18df2dee45de6d0a9ad4ab98bea501cd7090904141dc40d117b9e14.svg

Il est également possible de construire une hauteur en Scheme à l’aide de la fonction ly:make-pitch, voir plus bas.

Du point de vue de LilyPond, une hauteur a trois composantes, une octave, un nom de note, et une altération. Gardez à l’esprit qu’une hauteur n’est pas simplement une fréquence : do dièse et ré bémol sont des hauteurs différentes.

Plusieurs fonctions sont fournies pour manipuler les hauteurs, toutes documentées dans la page Scheme functions de la référence des propriétés internes. Voici les plus importantes.

(ly:make-pitch octave note alteration)

Construit une hauteur.

octave est un entier. Zéro correspond à l’octave du do central.

note va de 0, pour un do, à 6, pour un si.

alteration (argument facultatif) est une fraction : 0 signifie bécarre, 1/2, dièse, et -1/2, bémol. On peut donner n’importe quelle valeur, ce qui permet de représenter des doubles dièses ou encore des altérations microtonales.

Les constantes SHARP et FLAT sont respectivement définies à 1/2 et -1/2. Il existe également SEMI-SHARP, SEMI-FLAT et autres, toutes définies au début du fichier [scm/lily-library.scm][lily-library].

(ly:pitch-octave pitch)
(ly:pitch-notename pitch)
(ly:pitch-alteration pitch)

Fonctions pour extraire les composantes d’une hauteur

(ly:pitch-steps pitch)

Calcule nombre de notes du do central à cette hauteur. Cette fonction prend en compte l’octave et le nom de note, mais pas l’altération. Par exemple, elle renvoie 8 pour dis'' mais 9 pour ees''.

(ly:pitch-tones pitch)

Calcul le nombre de tons entre le do central et cette hauteur, renvoyé comme une fraction. Cette fonction prend en compte non seulement l’octave et le nom de note, mais aussi l’altération.

(ly:pitch-transpose pitch delta)
(+ pitch delta)

Transpose la hauteur pitch de la hauteur delta. C’est l’opération appliquée à chaque hauteur pitch de la musique dans le code \transpose c' #delta ....

Le résultat est défini de manière unique par les deux propriétés suivantes :

  • (ly:pitch-steps résultat) vaut (ly:pitch-steps pitch) plus (ly:pitch-steps delta),

  • (ly:pitch-tones résultat) vaut (ly:pitch-tones pitch) plus (ly:pitch-tones delta).

La seconde condition signifie que la transposition est bien ce que l’on appelle une transposition, c’est à dire qu’elle décale toutes les hauteurs de la même manière pour notre oreille. La première signifie que la transposition est également juste enharmoniquement (par exemple, transposer du do au la dièse change chaque hauteur en la hauteur qui est une sixte augmentée au-dessus, tandis qu’avec un si bémol, c’est une septième mineure).

La forme avec + est possible depuis la version 2.25.7.

(ly:pitch-diff pitch root)
(- pitch root)

Renvoie la hauteur delta telle que root transposée de delta vale pitch.

Le code \transpose #hauteur1 #hauteur2 ... transforme chaque hauteur h de la musique en (ly:pitch-transpose h (ly:pitch-diff hauteur2 hauteur2)).

La forme avec - est possible depuis la version 2.25.7.

Durées et moments#

Toute note possède une durée, qui définit comment elle s’affiche. Elle est généralement entrée juste après la hauteur. Ainsi, 8 ou 4..*3/8 sont des durées. Plus précisément, une durée est définie par trois composantes : un indicateur principal de longueur, un nombre de points d’augmentation, et un facteur multiplicatif. Dans les cas de 8 et 4..*3/8, les indicateurs de longueur correspondent à 8 et 4. Ils sont représentés par un log négatif en base 2 : 0 signifie une ronde, 1 une blanche, 2 une noire, 3 une croche, etc. Le facteur multiplicatif est une fraction. C’est la partie *3/8 de 4..*3/8. Lorsqu’il est défini, il modifie la longueur de la durée sans changer la manière dont la note s’affiche. La longueur a son importance pour la synchronisation entre les voix, pour l’espacement horizontal, ou encore le rendu MIDI. Observez l’effet des facteurs multiplicatifs dans cet exemple :

\version "2.25.8"

<< { c''4 4*1/2 4*1/2 4..*4/7 4 } \\ { c'4 4 4 4 } >>
Résultat../../images/f408ed92284d8bc8fea5f0cc7130bd1d64023a7b328c018fbbc3ece1a0e32072.svg

Un « moment » est une longueur ou un point précis dans le temps musical (penser au MIDI). En première approximation, c’est simplement une fraction. Néanmoins, les notes d’ornement viennent perturber cette vision, car elles auraient une longueur de zéro. C’est pourquoi un moment a en fait deux composantes, une longueur principale et une longueur d’ornement.

On peut obtenir la longueur d’une durée quelconque sous forme de moment. L’inverse n’est pas possible, tout simplement parce que deux durées différentes peuvent très bien avoir la même longueur. Les durées 16.. et 8*7/8 ont toutes les deux pour longueur un moment dont la longueur est 7/8 d’une croche. Dans la sortie graphique, la première donne lieu à une double croche doublement pointée, tandis que la seconde est simplement affichée comme une croche (dont on peut imaginer qu’elle fait partie d’une partition baroque où des n-olets sont écrits implicitement).

On entre la plupart du temps une durée avec la syntaxe LilyPond habituelle. Cela fonctionne aussi à l’intérieur de #{ ... #}, comme le montre cet exemple :

\version "2.25.8"

myDuration = ##{ 4.. #}
{ c' $myDuration }
Résultat../../images/89aa7a2ab7bc6779e397db03367115ab0176155daf7371bf2449894989f9a1a5.svg

On peut également créer une durée en Scheme. Quant aux moments, il ne sont pas visibles pour les utilisateurs qui ne se servent pas de Scheme, aussi on ne peut les construire qu’en Scheme.

(ly:make-duration length dot-count factor)

Crée une durée

(ly:duration-length duration)

Renvoie la longueur de duration sous forme d’un moment

(ly:duration-log duration)
(ly:duration-dot-count duration)
(ly:duration-scale duration)

Ces fonctions renvoient les différentes composantes d’une durée

(ly:make-moment main-part grace-part)

Crée un moment. main-part et grace-part sont respectivement la longueur principale et la longueur d’ornement, sous forme de fractions.

(ly:music-length music)

Renvoie la longueur totale de music sous forme de moment.

(ly:moment-main moment)
(ly:moment-grace moment)

Ces fonctions renvoient les composantes d’un moment, longueur principale ou longueur d’ornement.

(ly:moment-add moment1 moment2)
(+ moment1 moment2)
(ly:moment-sub moment1 moment2)
(- moment1 moment2)
(ly:moment-mul moment rational)
(* moment fraction)
(ly:moment-div moment rational)
(/ moment fraction)
(ly:moment-mod moment rational)

Opérations sur les moments

L’addition et la soustraction ajoutent et soustraient respectivement les longueurs principales et les longueurs d’ornement des deux moments. La multiplication et la division sont définies entre un moment et un rationnel (c’est à dire une fraction Scheme comme 5/6  ; notez que les entiers sont des cas particuliers de fractions en Scheme). En termes plus « matheux », les opérations sur les moments sont tout simplement celles d’un ℚ-espace vectoriel de dimension 2.

Les formes avec les opérateurs Scheme standard (+, -, * et /) sont possibles depuis la version 2.25.7.