lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Flexible lyric alignment


From: Jean Abou Samra
Subject: Re: Flexible lyric alignment
Date: Sun, 13 Nov 2022 23:03:38 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.1

Le 12/11/2022 à 16:38, Kieren MacMillan a écrit :
Hi all,

I know many of you follow a “Do first” process… so even though that’s not my 
process, here goes.  ;)

Here's a small example of this spacing “thorn”, and one way I might tweak it to 
fix the problem.

Notes:
– I realize it's constructed to avoid the very issue(s) that Jean raises (i.e., 
there are no lyrics in the measures on either side of the main one)
– I realize the spacing I ended up with is not “perfect” (a.k.a. “enemy of the 
good”)
– I realize there are at least a dozen other ways of tweaking the spacing to 
accomplish the same goal (i.e., making the tuplet notes evenly spaced)
– I realize the fix to this constructed example wouldn't fix the OP's issue 
(i.e., shifting the LyricText “out of the way”)

I just thought talking through a concrete example might bring clarity to what 
has so far been a pretty abstract discussion.

My question: How can the tweak I've made here be automated *only considering 
the notes and lyrics in question, and not worrying about what might [or might 
not] happen once there are elements in the surrounding moments/measures that 
might collide?



Well, we are kind of deviating from the topic of lyric spacing,
because this example isn't specific to lyrics, although this
situation probably occurs more often in lyrics than in other
contexts. You would have the same with a long text script, for
example. As you say yourself, what we'd like LilyPond to
do automatically here is not shifting the lyric text out
of the way, but adding more spacing to the other notes of
the tuplet.

Here's one way to do this, but don't be too excited: not only
is it hacky (in "fixable" ways), but it makes lots of assumptions
that hold in the example and won't hold in anything more complicated.
Some of the "fixable" ones are: the group is made of notes (not rests),
there are no clefs or such, the unevenness is caused by rods (not
springs; those aren't transparent to Scheme). More importantly,
it assumes that there are no notes interspersed between the notes
of the group in another voice. Also, it needs to trigger before-line-breaking
earlier than usual, so it might have bad side effects on scores
not even using \equalRodsGroup.

Basically, the idea is to read the rods between the (musical) columns
from a group of notes, and set them all to the max between them.


\version "2.23.80"

\layout {
  \context {
    \Score
    \override System.before-line-breaking =
      #(lambda (grob)
         (let ((elements (ly:grob-array->list (ly:grob-object grob 'all-elements))))
           (for-each
            (lambda (elt)
              (when (not (eq? 'NoteHead (grob::name elt)))
                (ly:grob-property elt 'springs-and-rods)))
            elements)))
  }
}

#(use-modules (ice-9 match))

#(define (successive-pairs lst)
   (let loop ((lst lst)
              (acc '()))
     (match lst
       ((or () (_))
        (reverse! acc))
       ((a . (and rest (b . rest2)))
        (loop rest
              (cons (cons a b)
                    acc))))))

equalRodsGroup =
#(define-music-function (music) (ly:music?)
   (let ((cols '())
         (done #f))
     #{
       {
         \temporary \override NoteHead.before-line-breaking =
           #(lambda (grob)
              (set! cols (cons (ly:item-get-column grob)
                               cols)))
         \temporary \override NoteHead.springs-and-rods =
           #(lambda (grob)
              (when (not done)
                (set! done #t)
                (let* ((ordered-cols (sort cols
                                           (comparator-from-key
                                            (lambda (c)
                                              (ly:grob-property c 'when))
                                            ly:moment<?)))
                       (pairs (successive-pairs ordered-cols))
                       (max-rod
                        (apply max
                               (map (match-lambda
                                     ((left . right)
                                      (assoc-get right
                                                 (ly:grob-object left 'minimum-distances)
                                                 -inf.0)))
                                    pairs))))
                  (for-each
                   (match-lambda
                    ((left . right)
                     (set! (ly:grob-object left 'minimum-distances)
                           (assq-set! (ly:grob-object left 'minimum-distances)
                                      right
                                      max-rod))))
                   pairs))))
         #music
         \revert NoteHead.before-line-breaking
         \revert NoteHead.springs-and-rods
       }
     #}))

\paper {
  top-margin = 0.5\in
  left-margin = 0.5\in
}

spacecase_notes = { R1 a'8 8 \equalRodsGroup { \tuplet 3/2 { 8 8 8 } } 4 4 R1 }
spacecase_lyrics = \lyricmode { This is spaced a bit poor -- ly! }

\score {
  <<
    \new Staff \new Voice = "melody" \spacecase_notes
    \new Lyrics \lyricsto "melody" \spacecase_lyrics
  >>
}



Very much looking forward to seeing what comes of this thread!


Speaking for myself, patches from me in this area are unlikely to
come anytime soon. I'll be happy if someone else works on this,
but be warned that "here be dragons".

Best,
Jean

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]