Les fonctions musicales 2. Commençons à faire quelque chose d’utile !

Traduction d’un article de Urs Liska

Dans l’article précédent, j’ai montré comment insérer du code Scheme dans les fichiers sources LilyPond. Nous avons pu écrire notre première fonction : avouons qu’elle n’était pas très utile. Aujourd’hui, nous allons nous attaquer à des fonctions qui font vraiment quelque chose, et utilisent des paramètres.

Petit rappel : une autre fonction statique

Remarque préliminaire : j’utilise le terme de fonction statique dans son sens premier, et non dans son acceptation en programmation orientée objet.

noteRouge =
#(define-music-function (parser location)()
   #{
     \once \override NoteHead.color = #red
     \once \override Stem.color = #red
   #})

\relative c' {
  c4 \noteRouge c c c
}

second-music-function

Comme dans l’article précédent, cette fonction retourne le code d’une expression musicale, avec cette différence qu’il ne s’agit pas là de notes mais de deux propriétés override qui vont colorer en rouge la note qui suit. Si vous souhaitez en faire plus, vous pouvez aussi colorer d’autres objets comme les hampes, ligatures, points, etc.

Une fonction plus souple grâce à ses paramètres

Ce serait une erreur de copier cette fonction à chaque fois que nous souhaitons changer de couleur. Il vaut mieux adapter la fonction en lui passant un paramètre de couleur. Dans l’article précédent, nous avons déjà vu comment ajouter des paramètres ou arguments à la fonction :

colorierNote =
#(define-music-function (parser location ma-couleur)
   (color?)
   #{
     \once \override NoteHead.color = #ma-couleur
     \once \override Stem.color = #ma-couleur
   #})

J’ai ajouté ma-couleur à la liste des paramètres, en lui affectant le type color?. Par convention, il faut ajouter la liste des types des
paramètres sur une ligne indépendante. Ce n’est que lorsque cette liste est vide qu’elle est accolée à la liste des paramètres – sinon c’est vraiment bizarre.

Cette fonction doit donc être appelée avec un paramètre de type color?.
Au sein du code Scheme, le paramètre est appelé simplement ma-couleur ;
au sein de la partie LilyPond, délimitée par #{ … #}, il faut
faire précéder le paramètre par un # comme nous l’avons déjà vu, et
appeler la couleur ainsi : #ma-couleur.

Notre fonction va maintenant renvoyer deux propriétés override, mais la couleur n’est plus codée en dur : ce sera la couleur passée en paramètre qui sera appliquée.

\relative c' {
  c4 \colorierNote #blue c \colorierNote #'(0.5 0.5 0) c c
}

third-music-function

Regardons maintenant comment nous avons utilisé la fonction. Le paramètre de type color? est produit par LilyPond. Nous avons indiqué à LilyPond de passer en Scheme grâce au signe # et avons ainsi passé à la fonction le paramètre Scheme évalué à blue. Nous pouvons aussi définir une couleur en ligne en indiquant la liste des 3 valeurs RGB, qui renverra cette valeur Scheme. Pour les débutants, il est souvent difficile de bien définir les valeurs Scheme en LilyPond. Elles sont tantôt écrites littéralement (comme les couleurs), parfois il faut les faire précéder d’un signe ', et d’autres fois les encadrer par '(). La pratique de Scheme dans Lilypond, bien plus que mon aide, est le meilleur moyen de trouver ses marques. Normalement, tout est indiqué dans le documentation de LilyPond concernant Scheme – peut-être est-ce d’ailleurs le moment de la relire.

Encore plus de souplesse : de la musique comme paramètre

L’étape suivante consiste à passer de la musique en paramètre. Ce paramètre a pour type ly:music? (à dire vrai, les fonctions et types préfixés par ly: ne sont pas du pur Scheme mais des éléments LilyPond).

rienFaire =
#(define-music-function (parser location ma-musique)
   (ly:music?)
   #{
     ma-musique
   #})

Cette fonction prend pour paramètre une expression musicale et retourne cette expression – ce qui n’est pas vraiment utile. Cela me permet toutefois d’illustrer le point suivant : le paramètre de type ly:music? est une expression musicale Scheme et nous voulons que la fonction nous retourne exactement cette expression. Il ne nous est donc pas utile de passer en mode LilyPond à l’intérieur de la fonction et de convertir l’expression LilyPond en Scheme. Nous pouvons donc écrire plus
simplement :

rienFaireDeux =
#(define-music-function (parser location ma-musique)
   (ly:music?)
   ma-musique)

La fonction retournera la valeur de ma-musique – ce qui revient exactement au même. On peut voir d’ailleurs que ces deux fonctions font la même chose :

\relative c' {
  c4 \rienFaire c \rienFaireDeux c c
}

fourth-music-function

Petite remarque : dans les deux cas, nous n’avons passé qu’une seule expression musicale, constituée d’une seule note. Dans la plupart des cas nous voudrons cependant passer une ensemble d’expressions musicales, comme nous allons le voir dans l’exemple suivant.

Colorier n’importe quelle musique avec n’importe quelle couleur

En guise de conclusion, nous allons écrire une fonction qui colorie n’importe quelle expression musicale avec une couleur de notre choix. Nous aurons besoin de deux paramètres : la couleur et la musique. Tout d’abord, nous allons modifier la couleur de plusieurs objets avec le paramètre couleur, puis produirons la musique passée en paramètre. Nous reviendrons enfin aux valeurs initiales de couleur pour les objets concernés. Je vais utiliser la fonction \temporary, uniquement disponible dans les versions stables à partir de 2.18, qui permet de revenir avec \revert non pas au noir d’origine, mais à la couleur employée juste avant. Si vous utilisez la version 2.16, n’écrivez pas \temporary.

colorierMusique =
#(define-music-function (parser location ma-couleur ma-musique)
   (color? ly:music?)
   #{
     \temporary \override NoteHead.color = $ma-couleur
     \temporary \override Stem.color = $ma-couleur
     \temporary \override Flag.color = $ma-couleur
     \temporary \override Beam.color = $ma-couleur
     \temporary \override Rest.color = $ma-couleur
     \temporary \override Slur.color = $ma-couleur
     \temporary \override PhrasingSlur.color = $ma-couleur
     \temporary \override Tie.color = $ma-couleur
     \temporary \override Script.color = $ma-couleur
     \temporary \override Dots.color = $ma-couleur
     
     #ma-musique
     
     \revert NoteHead.color
     \revert Stem.color
     \revert Flag.color
     \revert Beam.color
     \revert Rest.color
     \revert Slur.color
     \revert PhrasingSlur.color
     \revert Tie.color
     \revert Script.color
     \revert Dots.color
   #})

Pour corser l’exercice, j’ai inséré en paramètre de la musique un peu plus complexe, et appelé la fonction de différentes manières.

#ma-musique = \relative c' {
  c4. d8 e16 d r cis( d4) ~ | d1 \fermata
}

\relative c' {
  \colorierMusique #blue \ma-musique
  \colorierMusique #red { c4 c } d \colorierMusique #green e\f
  \colorierMusique #magenta \ma-musique
(Click to enlarge)

(Click to enlarge)

Vous constaterez que la fonction peut être alimentée soit par une seule note, soit par une expression musicale entre accolades, soit par un paramètre préalablement défini. Vous noterez aussi que les altérations et les nuances ne sont pas colorisées : il suffit d’ajouter les propriétés override correspondantes dans la fonction.

Tout semble bien fonctionner, maintenant, à une remarque près : l’écriture est très redondante, ce qui n’est pas très bon. Il faudrait factoriser tout cela dans une fonction à part. C’est ce que nous ferons dans un prochain article.

6 thoughts on “Les fonctions musicales 2. Commençons à faire quelque chose d’utile !

  1. Pierre-Luc Gauthier

    Merci Jean-Marc, tes articles sont super.

    Je crois qu’effectivement, il y a un besoin pour des pages d’explications en français sur Lilypond et Scheme.
    Je me demande par contre si c’est adéquat de le faire directement sur lilypondblog.org . Par exemple, des gens qui reçoivent des notifications à chaque nouvel article peuvent maintenant en recevoir dans une langue inattendu. Moi, je suis francophone et je n’aime pas tant l’idée de faire des commentaires en français sur un site d’expression anglophone. Qu’en penses-tu ?

    Moi aussi, j’aimerai beaucoup contribuer de manière similaire 🙂
    Que penses-tu de fr.lilypondblog.org ? Peut-être pourrions-nous proposer cette adresse à un admin du blog ?

    Reply
    1. Jean-Marc Legrand Post author

      Bonjour Pierre-Luc et merci pour les encouragements (note juste que les articles sont d’Urs et non de moi ;o) ).

      Je comprends tout à fait ce que tu dis sur les commentaires fr dans les articles en… pour ceux et celles qui ne maîrisent pas suffisamment l’anglais pour écrire un commentaire, c’est assez frustrant. L’idée de créer un domaine purement fr lié au blog est sans doute une bonne solution. Le seul bémol que j’y mets, c’est que pour ma part, je ne sais pas si j’aurai le temps d’y contribuer très souvent : mes traductions des articles sur Scheme répondent en fait à mon envie d’y comprendre qque chose, couplée au souhait de partager avec la communauté fr. Il s’agit d’un tir isolé, à moins que… Bon, je vais proposer à Urs d’ouvrir un domaine fr et je te tiens au courant.
      A + !
      JMarc

      Reply
  2. Jean-Alexis Montignies

    Il y a une erreur dans le script colorierMusique: au milieu du script il faut écrire #ma-musique

    Reply
  3. Martial R

    Bonjour
    supe r article
    Il y a une autre erreur : à la place de $my-color dans la 5e ligne
    ” \temporary \override NoteHead.color = $my-color ”
    il faut écrire $ma-couleur

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *