Hi Morten,

Le jeudi 22 février 2024 à 23:00 +0100, Morten Lemvigh a écrit :
> \version "2.24.1"
> 
> double =
> #(define-music-function (music)(ly:music?)
>    (let ((notes (ly:music-property music 'elements)))
>      (make-music 'SequentialMusic
>                  'elements
>                  (list
>                   (make-music 'SequentialMusic
>                               'elements notes)
>                   (make-music 'SequentialMusic
>                               'elements notes)))))
> 
> \relative c' {
>   \double {e4 e}
> }


Several things are wrong here.

First, although you are unwrapping `music`, you are not copying the individual
elements of `notes`. They end up duplicated in the output. This should never
happen, because music objects are mutable. \relative is in fact a good example
of this, but perhaps a simpler one is \scaleDurations: try

\scaleDurations 1/2 \double { e'1 1 }

and you will see that the whole notes are scaled by 1/4 instead of 1/2. The 
reason
is that calling [note1] and [note2] the two note objects, you end up with

  [note1] [note2] [note1] [note2]

and when \scaleDurations goes through the music and scales it, since [note1]
and [note2] both appear twice, they get scaled twice.

That's the reason you should always copy music with ly:music-deep-copy
or an equivalent if you need it to appear in several places.

In your example

\relative c' {
  \double {e4 e}
}

what happens is the following: \relative changes the first e4 into an absolute
e'4, to match the octave of c' . Then the second e is changed to e'4 as well,
to have the same octave as the first. Then the third e is processed, but it's
actually the same object as the first e4, which was mutated into e'4, so this
tells \relative to go an octave higher, and that e'4 is mutated a second time
into an e''4. And finally, the fourth e is processed, it's the same as the 
second
e which was turned into e', which goes an octave up, so it becomes e'''.
And that's why the end result is e''4 e''' e''4 e'''.

So this is already a better version:

double =
#(define-music-function (music)(ly:music?)
   (make-music 'SequentialMusic
               'elements (list (ly:music-deep-copy music)
                               (ly:music-deep-copy music))))

or more simply put:

double =
#(define-music-function (music)(ly:music?)
   #{ $music $music #})

but in fact this is still not correct because \relative is a somewhat
special beast. The problem is that

\relative c' {
  \double {e'4 e}
}

now unfolds to

\relative c' {
  { e'4 e e'4 e }
}

where the third e'4 goes an octave up compared to the second, but you
don't want that, you want it to be the same as the first e'4. For that
case, there is a special macro called make-relative. It's used like this:

\version "2.24.1"

double =
#(define-music-function (music) (ly:music?)
   (make-relative (music) music
     #{ $music $music #}))


Best,
Jean

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to