scheme : type d' arguments pour \transpose

Bonjour tout le monde.
Qui pourrait me dire quel type je doit mettre à la place de (ly:music?) pour que la commande "\transpose c $note" soit acceptée.
Pour le moment, on obtient le message :
"syntax error, unexpected MUSIC_IDENTIFIER, expecting NOTENAME_PITCH or TONICNAME_PITCH"

Merci

%%%%%%%%
\version "2.11.34"
A = { c2 e g }

accord = #(define-music-function (parser location note) (ly:music?)
#{
         \transpose c $note \relative { \A \A }
#})

\accord g,

%%%%%%%%%

Ce n'est pas malheureusement pas possible de faire ça de façon aussi simple.

Quand tu écris :

   \accord g,

LilyPondva évaluer l'expression entre #{ #} en remplaçant le $note
par un identifiant dont la valeur est celle passée en argument à ta
fonction, c'est-à-dire quelque chose d'équivalent à :

   tmpVariable = g,
   \transpose c \tmpVariable \relative { \A \A }

Or ceci n'est pas une expression LilyPond correcte, le message d'erreur que tu
obtiens signifie que à la place de l'identifant (MUSIC_IDENTIFIER), le parser
pensait trouver un nom de note (NOTENAME_PITCH or TONICNAME_PITCH). Ca, c'est
pour la mauvaise nouvelle.

Mais il y a tout de même une solution. Pour faire ce que tu souhaites, la
première étape consiste à écrire l'expression que tu veux construire avec
ta fonction, et voir à quoi elle ressemble en Scheme, en utilisant
\displayMusic:

   \displayMusic \transpose g, \relative { \A \A }

Ensuite, il s'agira de faire une fonction qui construit une expression de ce type,
en remplaçant la partie qui correspond au "g," par l'argument de ta fonction (la
variable note), et idem pour la variable A.

nicolas

···

Le 30 nov. 07 à 00:50, Gilles THIBAULT a écrit :

Bonjour tout le monde.
Qui pourrait me dire quel type je doit mettre à la place de (ly:music?) pour que la commande "\transpose c $note" soit acceptée.
Pour le moment, on obtient le message :
"syntax error, unexpected MUSIC_IDENTIFIER, expecting NOTENAME_PITCH or TONICNAME_PITCH"

Merci

%%%%%%%%
\version "2.11.34"
A = { c2 e g }

accord = #(define-music-function (parser location note) (ly:music?)
#{
       \transpose c $note \relative { \A \A }
#})

\accord g,

%%%%%%%%%

Merci de ta réponse.

Mais il y a tout de même une solution. Pour faire ce que tu souhaites, la
première étape consiste à écrire l'expression que tu veux construire avec
ta fonction, et voir à quoi elle ressemble en Scheme, en utilisant
\displayMusic:
  \displayMusic \transpose g, \relative { \A \A }

C'est bien ce que j'avais essayé, mais voilà un extrait de ce que ça donne pour
        A = \relative { c'2 e g }
        \displayMusic \transpose c g, \A
=>
%%%%%%%%%%%%%%
(make-music
  'TransposedMusic
  'element
  (make-music
    'RelativeOctaveMusic
    'element
    (make-music
      'SequentialMusic
      'elements
      (list (make-music
              'EventChord
              'elements
              (list (make-music
                      'NoteEvent
                      'duration
                      (ly:make-duration 1 0 1 1)
                      'pitch
                      (ly:make-pitch 0 4 0))))
            (make-music .....
%%%%%%%%%%%%%

Comme on peut le voir, il n'y a aucune trace de g' dans la représentation donnée par \displayMusic. Le listing ci-dessus correspond à la liste déjà développée et transposée = {g'2 b' d''}: (le (ly:make-pitch 0 4 0) correspond à g'2). Le * 'TransposedMusic* sert simplement à indiquer que la musique a été transposée mais aucune trace de combien elle l'a été ...
Je ne vois pas bien comment je pourrais me servir des renseignements fournis ici.

Gilles

En effet. Donc dans ce cas, il faut regarder ce que fait le parser quand il
rencontre le mot clé \transpose dans le fichier source lily/parser.yy, et
essayer de faire pareil.

TRANSPOSE pitch_also_in_chords pitch_also_in_chords music {
  Pitch from = *unsmob_pitch ($2);
  Pitch to = *unsmob_pitch ($3);
  SCM pitch = pitch_interval (from, to).smobbed_copy ();
  $$ = MAKE_SYNTAX ("transpose-music", @$, pitch, $4);

Le jeu de piste n'est pas terminé. Ici ça dit que l'on fabrique un objet
avec "transpose-music", qui est défini dans le fichier source
scm/ly-syntax-constructors.scm :

(define-ly-syntax-simple (transpose-music pitch music)
   (make-music 'TransposedMusic
           'element (ly:music-transpose music pitch)))

Donc on va essayer de faire comme le parser, à partir d'une note de départ,
une note de destination, et la musique à transposer, de générer la transposition
en utilisant ly:music-transpose.

L'équivalent en Scheme de la fonction pitch_interval qu'on voit dans parser.yy
est ly:pitch-diff (avec des arguments inversés). On va devoir écrire quelque chose
comme :

   (ly:music-transpose music (ly:pitch-diff to from))

où to est le "pitch" de la note passée en argument, et from le pitch de la note c.

Pour récupérer cette propriété pitch, il faut repérer où elle se loge dans
l'expression musicale représentant une note :

   \displayMusic g,
==>
   (make-music 'EventChord
     'elements (list (make-music 'NoteEvent
                       'duration (ly:make-duration 2 0 1 1)
                       'pitch (ly:make-pitch -2 4 0))))

Donc, à partir d'une note, on obtient sa propriété pitch en faisant :

   (ly:music-property (car (ly:music-property note 'elements)) 'pitch)

Le pitch de la note "c" est également obtenu en invoquant \displayMusic :

   (ly:make-pitch -1 0 0)

On a maintenant tous les éléments permettant de construire à la main une
transposition.

   mytranspose =
   #(define-music-function (parser location to-note music)
                           (ly:music? ly:music?)
      (let ((from (ly:make-pitch -1 0 0))
            (to (ly:music-property (car (ly:music-property to-note 'elements))
                                   'pitch)))
        (ly:music-transpose music (ly:pitch-diff to from))))

   \displayMusic \mytranspose g, a'
   \displayMusic \transpose c g, a'
==>
   (make-music 'EventChord
     'elements (list (make-music 'NoteEvent
                      'duration (ly:make-duration 2 0 1 1)
                      'pitch (ly:make-pitch 0 2 0))))
   (make-music 'TransposedMusic
    'element (make-music 'EventChord
               'elements (list (make-music 'NoteEvent
                                 'duration (ly:make-duration 2 0 1 1)
                                 'pitch (ly:make-pitch 0 2 0)))))

Pour avoir un résultat identique au \transpose original il ne reste qu'à enrober
le résultat de notre fonction dans (make-music 'TransposedMusic etc:

   mytranspose =
   #(define-music-function (parser location to-note music)
                           (ly:music? ly:music?)
      (let ((from (ly:make-pitch -1 0 0))
            (to (ly:music-property (car (ly:music-property to-note 'elements))
                                   'pitch)))
        (make-music 'TransposedMusic
          'element (ly:music-transpose music (ly:pitch-diff to from)))))

Adapter cette fonction pour faire la fonction accord que tu souhaites devrait
être assez facile.

nicolas

···

Le 1 déc. 07 à 00:20, Gilles THIBAULT a écrit :

C'est bien ce que j'avais essayé, mais voilà un extrait de ce que ça donne pour
      A = \relative { c'2 e g }
      \displayMusic \transpose c g, \A
=>
[...]

Comme on peut le voir, il n'y a aucune trace de g' dans la représentation donnée par \displayMusic. Le listing ci-dessus correspond à la liste déjà développée et transposée = {g'2 b' d''}: (le (ly:make-pitch 0 4 0) correspond à g'2). Le * 'TransposedMusic* sert simplement à indiquer que la musique a été transposée mais aucune trace de combien elle l'a été ...
Je ne vois pas bien comment je pourrais me servir des renseignements fournis ici.

Ouf, merci beaucoup pour cette réponse conséquente.
Je suis en fait, en train de faire un cahier de gammes pour mes élèves
clarinettistes d'où ma tentative de faire une fonction qui utilise un
canevas fixe et qui est transposé à souhait dans tous les tons.
Au delà de l'aide ponctuelle apportée ici, on peut aussi recueillir beaucoup de
renseignements sur la méthodologie à adopter pour écrire des
fonctions schemes. En particulier, j'avais bien tenté de trouver dans les
fichiers *.scm et *.ly du repertoire usr\share\lilypond\current,
l'implémentation de \transpose, mais sans succès.
Jamais je n'avais eu l'idée de rechercher dans les fichiers sources !
Bref, je vais étudier tout ça et je transmettrai ici le résultat. (je pense
que d'autres profs pourront éventuellement être interessés pour adapter ce
cahier pour leur propre instrument).

Un cahier de gammes, c'est les élèves qui vont être contents :slight_smile:

Gilles

···

-----------------------------------------------
Nicolas Sceaux a écrit
<
En effet. Donc dans ce cas, il faut regarder ce que fait le parser
quand il
rencontre le mot clé \transpose dans le fichier source lily/parser.yy,
et
essayer de faire pareil.

TRANSPOSE pitch_also_in_chords pitch_also_in_chords music {
Pitch from = *unsmob_pitch ($2);
Pitch to = *unsmob_pitch ($3);
SCM pitch = pitch_interval (from, to).smobbed_copy ();
$$ = MAKE_SYNTAX ("transpose-music", @$, pitch, $4);

Le jeu de piste n'est pas terminé. Ici ça dit que l'on fabrique un objet
avec "transpose-music", qui est défini dans le fichier source
scm/ly-syntax-constructors.scm :

(define-ly-syntax-simple (transpose-music pitch music)
   (make-music 'TransposedMusic
         'element (ly:music-transpose music pitch)))

Donc on va essayer de faire comme le parser, à partir d'une note de
départ,
une note de destination, et la musique à transposer, de générer la
transposition
en utilisant ly:music-transpose.

L'équivalent en Scheme de la fonction pitch_interval qu'on voit dans
parser.yy
est ly:pitch-diff (avec des arguments inversés). On va devoir écrire
quelque chose
comme :

   (ly:music-transpose music (ly:pitch-diff to from))

où to est le "pitch" de la note passée en argument, et from le pitch
de la note c.

Pour récupérer cette propriété pitch, il faut repérer où elle se loge
dans
l'expression musicale représentant une note :

   \displayMusic g,
==>
   (make-music 'EventChord
     'elements (list (make-music 'NoteEvent
                       'duration (ly:make-duration 2 0 1 1)
                       'pitch (ly:make-pitch -2 4 0))))

Donc, à partir d'une note, on obtient sa propriété pitch en faisant :

   (ly:music-property (car (ly:music-property note 'elements)) 'pitch)

Le pitch de la note "c" est également obtenu en invoquant
\displayMusic :

   (ly:make-pitch -1 0 0)

On a maintenant tous les éléments permettant de construire à la main une
transposition.

   mytranspose =
   #(define-music-function (parser location to-note music)
                           (ly:music? ly:music?)
      (let ((from (ly:make-pitch -1 0 0))
            (to (ly:music-property (car (ly:music-property to-note
'elements))
                                   'pitch)))
        (ly:music-transpose music (ly:pitch-diff to from))))

   \displayMusic \mytranspose g, a'
   \displayMusic \transpose c g, a'
==>
   (make-music 'EventChord
     'elements (list (make-music 'NoteEvent
                      'duration (ly:make-duration 2 0 1 1)
                      'pitch (ly:make-pitch 0 2 0))))
   (make-music 'TransposedMusic
    'element (make-music 'EventChord
               'elements (list (make-music 'NoteEvent
                                 'duration (ly:make-duration 2 0 1 1)
                                 'pitch (ly:make-pitch 0 2 0)))))

Pour avoir un résultat identique au \transpose original il ne reste
qu'à enrober
le résultat de notre fonction dans (make-music 'TransposedMusic etc:

   mytranspose =
   #(define-music-function (parser location to-note music)
                           (ly:music? ly:music?)
      (let ((from (ly:make-pitch -1 0 0))
            (to (ly:music-property (car (ly:music-property to-note
'elements))
                                   'pitch)))
        (make-music 'TransposedMusic
          'element (ly:music-transpose music (ly:pitch-diff to from)))))

Adapter cette fonction pour faire la fonction accord que tu souhaites
devrait
être assez facile.

nicolas

Salut à tous,

je suis sur le même travail avec mes flûtistes. Mais je ne comprend
rien à a ce que vous avez écrit. est-ce que qqn peut faire une
explication de texte ?
Ou ce trouve le schéma de base, ou ce trouve le schéma transposé.
J'espère que l'un d'entre vous aura le temps de faire un peut de formation.
Merci
Christophe

Gilles THIBAULT a écrit :

···

<div class="moz-text-flowed" style="font-family: -moz-fixed">
Ouf, merci beaucoup pour cette réponse conséquente.
Je suis en fait, en train de faire un cahier de gammes pour mes élèves
clarinettistes d'où ma tentative de faire une fonction qui utilise un
canevas fixe et qui est transposé à souhait dans tous les tons.
Au delà de l'aide ponctuelle apportée ici, on peut aussi recueillir
beaucoup de
renseignements sur la méthodologie à adopter pour écrire des
fonctions schemes. En particulier, j'avais bien tenté de trouver dans les
fichiers *.scm et *.ly du repertoire usr\share\lilypond\current,
l'implémentation de \transpose, mais sans succès.
Jamais je n'avais eu l'idée de rechercher dans les fichiers sources !
Bref, je vais étudier tout ça et je transmettrai ici le résultat. (je
pense
que d'autres profs pourront éventuellement être interessés pour
adapter ce
cahier pour leur propre instrument).

Un cahier de gammes, c'est les élèves qui vont être contents :slight_smile:

Gilles

-----------------------------------------------
Nicolas Sceaux a écrit
<
En effet. Donc dans ce cas, il faut regarder ce que fait le parser
quand il
rencontre le mot clé \transpose dans le fichier source lily/parser.yy,
et
essayer de faire pareil.

TRANSPOSE pitch_also_in_chords pitch_also_in_chords music {
Pitch from =unsmob_pitch ($2);
Pitch to =unsmob_pitch ($3);
SCM pitch =itch_interval (from, to).smobbed_copy ();
$$ =AKE_SYNTAX ("transpose-music", @$, pitch, $4);

Le jeu de piste n'est pas terminé. Ici ça dit que l'on fabrique un objet
avec "transpose-music", qui est défini dans le fichier source
scm/ly-syntax-constructors.scm :

(define-ly-syntax-simple (transpose-music pitch music)
  (make-music 'TransposedMusic
        'element (ly:music-transpose music pitch)))

Donc on va essayer de faire comme le parser, à partir d'une note de
départ,
une note de destination, et la musique à transposer, de générer la
transposition
en utilisant ly:music-transpose.

L'équivalent en Scheme de la fonction pitch_interval qu'on voit dans
parser.yy
est ly:pitch-diff (avec des arguments inversés). On va devoir écrire
quelque chose
comme :

  (ly:music-transpose music (ly:pitch-diff to from))

où to est le "pitch" de la note passée en argument, et from le pitch
de la note c.

Pour récupérer cette propriété pitch, il faut repérer où elle se loge
dans
l'expression musicale représentant une note :

  \displayMusic g,

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

Donc, à partir d'une note, on obtient sa propriété pitch en faisant :

  (ly:music-property (car (ly:music-property note 'elements)) 'pitch)

Le pitch de la note "c" est également obtenu en invoquant
\displayMusic :

  (ly:make-pitch -1 0 0)

On a maintenant tous les éléments permettant de construire à la main une
transposition.

  mytranspose #(define-music-function (parser location to-note music)
                          (ly:music? ly:music?)
     (let ((from (ly:make-pitch -1 0 0))
           (to (ly:music-property (car (ly:music-property to-note
'elements))
                                  'pitch)))
       (ly:music-transpose music (ly:pitch-diff to from))))

  \displayMusic \mytranspose g, a'
  \displayMusic \transpose c g, a'

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

Pour avoir un résultat identique au \transpose original il ne reste
qu'à enrober
le résultat de notre fonction dans (make-music 'TransposedMusic etc:

  mytranspose #(define-music-function (parser location to-note music)
                          (ly:music? ly:music?)
     (let ((from (ly:make-pitch -1 0 0))
           (to (ly:music-property (car (ly:music-property to-note
'elements))
                                  'pitch)))
       (make-music 'TransposedMusic
         'element (ly:music-transpose music (ly:pitch-diff to from)))))

Adapter cette fonction pour faire la fonction accord que tu souhaites
devrait
être assez facile.

nicolas

</div>

--
Christophe GODEFROY