Subject: Scheme : récupérer des valeurs de propriété

From: Éditions IN NOMINE<[email-masked]>
Date: Wed, 22 Sep 2010 18:31:28 +0200

Bonjour.

Je suis en train de me faire un série d'exercices Scheme consistant à 
écrire en Scheme des fonctions toutes faites de Lily (ce qui fera 
l'objet de quelques pages web sur mon futur blog, sans doute).

En ce moment, je souhaite écrire une fonction qui augmente de 1 degré 
une note.
J'ai besoin de récupérer le b de 'pitch
                      (ly:make-pitch a b c))
de façon à l'augmenter de 1 pour le réinjecter dans la note passée en 
argument.

Ma fonction débute ainsi :

ajouterundegre = #(define-music-function (parser location note)(ly:music?)
          "ajoute 1 au second chiffre du pitch"
          (let ((result-note (ly:music-deep-copy note)))   ;copie locale 
de la note argument
               ((result-pitch (ly:music-property (first 
(ly:music-property result-note 'elements))                             
     'pitch))) ;copie locale du pitch de result-note

Comment faire pour récupérer le chiffre b du pitch, svp ?
La solution me permettrait d'étendre ce concept à bien d'autres 
fonctions. J'avoue ne pas avoir vu passer ce truc dans la doc : j'ai dû 
cligner des yeux au mauvais endroit !

Bonne soirée !

JMarc

---

From: "Gilles THIBAULT" <[email-masked]>
Date: Thu, 23 Sep 2010 17:51:25 +0200

J'ai besoin de récupérer le b de    'pitch
                       (ly:make-pitch a b c))
  de façon à l'augmenter de 1 pour le réinjecter dans la note passée en argument.

  (ly:pitch-octave result-pitch ) récupère a

  (ly:pitch-notename result-pitch ) récupère b

  (ly:pitch-alteration result-pitch ) récupère c
Toutes les fonctions de pitch (sauf ly:make-pitch) commence par ly:pitch

Bonne fin de semaine

Gilles

---

From: Éditions IN NOMINE<[email-masked]>
Date: Thu, 23 Sep 2010 18:12:58 +0200

Merci pour cette réponse qui confirme ce que j'ai glané aujourd'hui 
dans la doc Notation... Le fait est que j'aimerais savoir où trouver ce 
type de renseignement... ça doit bien être qque part ! ;-)
Quand tu m'écris : "Toutes les fonctions de pitch (sauf ly:make-pitch) 
commence par ly:pitch", en fait, j'aimerais avoir la liste de ces 
fonctions de pitch, parce que c'est pas évident à inventer! :-P

Bon, ça avance quand-même ! J'en suis donc là de ma fonction :

\version "2.13"

%le pitch est une propriété appartenant au 'NoteEvent, de la forme 
(ly:make-pitch a b c)
%où a = n° d'octave (zéro pour c'), b = n° du degré (zéro pour le c), c 
= 1/2 (dièse) ou -1/2 (bémol)
%a=pitch-octave, b=pitch-notename, c=pitch-alteration

ajouteundegre = #(define-music-function
                       (parser location note)(ly:music?)
                       "augmente d'un degré une note en ajoutant 1 au 
pitch-notename"
                       (let
                           (
                             (result-note (ly:music-deep-copy note))
                             (p (ly:music-property result-note 'pitch))
                             (o (ly:pitch-octave pitch))
                             (n (ly:pitch-octave pitch))
                             (a (ly:pitch-alteration pitch))
                           )
                           (set! p (ly:make-pitch o (+ 1 n) a))
*(set! (ly:music-property result-note 'pitch) p)*
                           result-note
                           )
                        )
\score{
\ajouteundegre c4
}

J'aurais pu mettre, à la place de la ligne en gras :
(ly:music-set-property! result-note 'pitch p)
ce qui aurait donné la même chose.

Bon d'abord, je reçois un message de Lily, pas content, qui me dit :

"While evaluating arguments to ly:music-property in expression 
(ly:music-property result-note (quote pitch)): Unbound variable: result-note
interruption avec le code 1.

Je ne comprends pas pourquoi il trouve que ma belle variable locale 
result-note est unbound ?
Si ça se trouve, c'est une bête histoire de parenthèses : j'ai bcp de 
mal avec ces bouzins dans tous les sens !

Bonne fin de semaine à toute la troupe !

JMarc

---

From: "Gilles THIBAULT" <[email-masked]>
Date: Thu, 23 Sep 2010 18:55:14 +0200

Merci pour cette réponse qui confirme ce que j'ai glané aujourd'hui dans la doc Notation... Le fait est que j'aimerais savoir où trouver ce type de renseignement... ça doit bien être qque part ! ;-) 
  Quand tu m'écris : "Toutes les fonctions de pitch (sauf ly:make-pitch) commence par ly:pitch", en fait, j'aimerais avoir la liste de ces fonctions de pitch, parce que c'est pas évident à inventer! :-P 

http://lilypond.org/doc/v2.12/Documentation/user/lilypond/Scheme-functions#Scheme-functions

Pour la version 2.13 je sais pas.

  %le pitch est une propriété appartenant au 'NoteEvent, de la forme (ly:make-pitch a b c)
  %où a = n° d'octave (zéro pour c'), b = n° du degré (zéro pour le c), c = 1/2 (dièse) ou -1/2 (bémol)
  %a=pitch-octave, b=pitch-notename, c=pitch-alteration

                        "augmente d'un degré une note en ajoutant 1 au pitch-notename"
                            (set! (ly:music-property result-note 'pitch) p)
                            result-note
                            )
                         )
  \score{
  \ajouteundegre c4
  }

  "While evaluating arguments to ly:music-property in expression (ly:music-property result-note (quote pitch)): Unbound variable: result-note
  interruption avec le code 1.

  Je ne comprends pas pourquoi il trouve que ma belle variable locale result-note est unbound ?
  Si ça se trouve, c'est une bête histoire de parenthèses : j'ai bcp de mal avec ces bouzins dans tous les sens !

  JMarc

Il y a 3 petites erreurs, dont 1 d'étourderie
1-
Si tu fais :
\ajouteundegre \displayMusic c4

tu obtiens :
(make-music
  'EventChord
  'elements
  (list (make-music
          'NoteEvent
          'duration
          (ly:make-duration 2 0 1 1)
          'pitch
          (ly:make-pitch -1 0 0))))

Tu n'obtiens pas une note ( 'NoteEvent ), mais un 'EventChord. Donc l'extraction du pitch est un peu moins direct
(voir ci-dessous )

2- l'erreur d'étourderie :
Tu appelles p le (ly:music-property result-note 'pitch), puis dans les lignes suivantes tu l'appelles pitch !

3-
En scheme, dans une instruction let, chaque "variable" doivent être indépendante les unes des autres. Si tu veux utiliser le resultat d'une ligne1 dans la ligne 2, tu dois utiliser let* à la place.

Donc ça donne un truc comme ça :

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ajouteundegre = #(define-music-function (parser location note)(ly:music?)
"augmente d'un degré une note en ajoutant 1 au pitch-notename"
(let*      
    ( 
      (result-chord (ly:music-deep-copy note))
      (result-note (car (ly:music-property result-chord 'elements)))
      (p (ly:music-property result-note 'pitch))
      (o (ly:pitch-octave p))
      (n (ly:pitch-octave p))
      (a (ly:pitch-alteration p))
    )
    (set! p (ly:make-pitch o (+ 1 n) a))
    (set! (ly:music-property result-note 'pitch) p)
    result-note
    )
 )
\score{
\ajouteundegre c'4
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Bon courage.

Gilles

---

From: Éditions IN NOMINE<[email-masked]>
Date: Thu, 23 Sep 2010 19:03:01 +0200

>
>     Quand tu m'écris : "Toutes les fonctions de pitch (sauf
>     ly:make-pitch) commence par ly:pitch", en fait, j'aimerais avoir
>     la liste de ces fonctions de pitch, parce que c'est pas évident à
>     inventer!
>
Houlla, ça, ça veut dire que je trouverai jamais .... :'(
> Tu n'obtiens pas une note ( 'NoteEvent ), mais un 'EventChord. Donc 
> l'extraction du pitch est un peu moins direct
> (voir ci-dessous )
ZE piège... je m'emmelle les pinceaux dans les niveaux... c'est le but 
de mes exercices...
> //
Et c'est parti pour 2 heures de flagellation avec nerf de boeuf 
clouté... c'est le tarif à la maison ! :-P
> 3-
> En scheme, dans une instruction let, chaque "variable" doivent être 
> indépendante les unes des autres. Si tu veux utiliser le resultat 
> d'une ligne1 dans la ligne 2, tu dois utiliser let* à la place.
Ah ça aussi il va falloir que je creuse : les !, les *, et quand il n'y 
a rien. J'ai survolé le tuto scheme de lily, donc punition ! Nerf de 
boeuf + 1 heure...
> Donc ça donne un truc comme ça :
Champion du monde ! En plus j'ai bien tout compris ! 8-)
Merci pour tout, je viens de faire un grand pas dans le monde souterrain 
de lilyScheme...

JMarc

---

From: "Gilles THIBAULT" <[email-masked]>
Date: Thu, 23 Sep 2010 22:42:40 +0200

Ah ça aussi il va falloir que je creuse : les !, les *, et quand il n'y a rien. J'ai survolé le tuto scheme de lily, donc punition ! Nerf de boeuf + 1 heure...

Le guide de référence se trouve ici :
http://www.gnu.org/software/guile/manual/guile.html
et en particulier le chapitre 5 :
http://www.gnu.org/software/guile/manual/guile.html#API-Reference
C'est très spartiate ( pas de tuto), c'est en anglais, mais ça a le mérite d'exister.
Pour les let et let* par exemple tu as une explication succinte ici :
http://www.gnu.org/software/guile/manual/guile.html#Local-Bindings

  Champion du monde ! 
Euh en fait j'ai fait une erreur dans la dernière ligne. Il faut mettre, je pense, result-chord et non result-note comme resultat de la fonction. On voit ici que Lilypond a immédiatement corriger en englobant le result-note dans un 'EventChord pour que le code reste valide. ( il suffit de faire un \displayMusic \ajouteundegre c'4 pour s'en assurrer ). Pas mal fait ce programe Lilypond !
Bonne soirée.

Gilles

---

From: "Gilles THIBAULT" <[email-masked]>
Date: Thu, 23 Sep 2010 22:58:25 +0200

Euh en fait j'ai fait une erreur dans la dernière ligne. 

Oups.J'ai trouvé une autre erreur d'étourderie à la ligne où n est déclaré (n (ly:pitch-notename  p)) et non (n (ly:pitch-octave p)).
Du coups c'était un hasard si ça marchait avec do ...
Cette version devrait marcher avec toutes les notes.

%%%%%%%%%%%%%%%
      (n (ly:pitch-notename  p))
    result-chord
    )
 )
\score{
\ajouteundegre c'4
}
%%%%%%%%%%%%%%%%%

Bon j'arrête pour ce soir.

Gilles