lilypond-user
[Top][All Lists]
Advanced

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

Re: Nested tuplet ratio notation


From: Valentin Petzel
Subject: Re: Nested tuplet ratio notation
Date: Fri, 28 Jul 2023 23:44:56 +0200

Hello Jean, Hello Lib,

in fact rather than constructing a tuplet marking using markup we can directly 
use a real tuplet number in the \rhythm markup:

\rhythm {
    % Change padding of Tuplet to be relative to size of Number,
    % so that distance to bracket does not depend on fontsize
    \override TupletBracket.padding =
    #(lambda (grob)
        (let* ((number (ly:grob-object grob 'tuplet-number))
                (ext (ly:grob-extent number number Y))
                (ext (interval-length ext)))
            (* 0.9 ext)))
    \tuplet 5/4 c8
}

There is a small additional override that makes the gap between Tuplet and 
note (given by TupletBracket.padding) not depend on the font size (the default 
is fixed at 1.2 staff units). This hat the advantage that we can easily tell 
Lilypond to show a Bracket:

\rhythm {
    % Change padding of Tuplet to be relative to size of Number,
    % so that distance to bracket does not depend on fontsize
    \override TupletBracket.padding =
    #(lambda (grob)
        (let* ((number (ly:grob-object grob 'tuplet-number))
                (ext (ly:grob-extent number number Y))
                (ext (interval-length ext)))
            (* 0.9 ext)))
    \override TupletBracket.bracket-visibility = ##t
    \override TupletBracket.shorten-pair = #'(-1.7 . -1.8)
    \tuplet 5/4 c8
}

(the shorten-pair is necessary to get a reasonable Bracket on a single note, 
else the tuplet Bracket would END at the left of the note and START at the 
right, which looks quite strange).

Also I’d change the design a bit:
I’d add some little space between number and note, add some space around the : 
and set the text in upright font rather than italic.

Also instead of handling the spacing by overriding TupletBracket.padding and 
TupletNumber.Y-offset I’d rather change the stencil function of TupletNumber to 
properly align things. This way the TupletBracket can still be positioned 
automatically, instead of having to fine tune Bracket padding and Number offset:

\override TupletNumber.stencil =
#(lambda (grob)
     (grob-interpret-markup
      grob
      (markup #:center-align #:translate-scaled '(0 . -0.5) (ly:grob-property 
grob 'text))))

Putting this all together this might look like this:

\new Staff
{
  \relative c'
  \repeat unfold 5 {
    \override TupletBracket.outside-staff-priority = #0
    \override TupletBracket.bracket-visibility = ##t
    \tuplet 5/4 {
      \override TupletNumber.text = \markup {
        \upright
        \concat {
          5
          \hspace #0.2
          \magnify #0.5
            \rhythm { c8 }
          " : "
          4
          \hspace #0.2
          \magnify #0.5
            \rhythm {
                % Change padding of Tuplet to be relative to size of Number,
                % so that distance to bracket does not depend on fontsize
                \override TupletBracket.padding =
                #(lambda (grob)
                   (let* ((number (ly:grob-object grob 'tuplet-number))
                          (ext (ly:grob-extent number number Y))
                          (ext (interval-length ext)))
                     (* 0.9 ext)))
                \tuplet 5/4 c8
            }
        }
      }
      \override TupletNumber.stencil =
      #(lambda (grob)
         (grob-interpret-markup
          grob
          (markup #:center-align #:translate-scaled '(0 . -0.5) (ly:grob-
property grob 'text))))
      \tuplet 5/4 {  c8[ c c c c]  }
    }
  }
}


Finally I’d pack this code into a function to make changing different such 
texts easier:

#(define* ((tuplet-number::custom-text duration ratio1 ratio2 #:optional 
(additional-overrides (empty-music))) grob)
   (let* ((ev (event-cause grob))
          (den (ly:event-property ev 'denominator))
          (num (ly:event-property ev 'numerator))
          (music1
           #{
             % Change padding of Tuplet to be relative to size of Number,
             % so that distance to bracket does not depend on fontsize
             \override TupletBracket.padding =
             #(lambda (grob)
                (let* ((number (ly:grob-object grob 'tuplet-number))
                       (ext (ly:grob-extent number number Y))
                       (ext (interval-length ext)))
                  (* 0.9 ext)))
             $additional-overrides
             $(if (fraction? ratio1) #{ \tuplet #ratio1 c$duration #} #{ 
c$duration #})
           #})
          (music2
           #{
             % Change padding of Tuplet to be relative to size of Number,
             % so that distance to bracket does not depend on fontsize
             \override TupletBracket.padding =
             #(lambda (grob)
                (let* ((number (ly:grob-object grob 'tuplet-number))
                       (ext (ly:grob-extent number number Y))
                       (ext (interval-length ext)))
                  (* 0.9 ext)))
             $additional-overrides
             $(if (fraction? ratio2) #{ \tuplet #ratio2 c$duration #} #{ 
c$duration #})
           #}))
     (markup
      #:upright
      #:concat
      (
        (number->string den)
        #:hspace 0.2
        #:magnify 0.5 #:rhythm music1
        " : "
        (number->string num)
        #:hspace 0.2
        #:magnify 0.5 #:rhythm music2
      ))))

This for example is a function of three parameters duration, ratio1, ratio2 
and optionally additional-overrides, where duration is a lilypond duration of 
of the note shown in the text, ratio1 and ratio2 are either a fraction (as 
pair) to represent the fraction of the tuplet in the text, ratio1 for the first 
position and ratio2 for the second one, or #f if no such tuplet should be 
printed at the second position, and additional-overrides is some music that is 
inserted before the notes, allowing us to add additional overides or stuff. 
This function will automatically derive the numbers (e.g. 5:4) from the 
tuplet.

E.g the tuplet in this example turns into

\override TupletNumber.text = #(tuplet-number::custom-text #{ 8 #} #f '(5 . 
4))

(duration is 8th, first note has not tuplet, second has 5/4).

For a showcase example checkout the appended file. Of course this could be 
extended if required: For example instead of a sigle ratio or false the 
function could take a list of ratios to create multiple tuplets.

Cheers,
Valentin

Am Freitag, 28. Juli 2023, 13:49:59 CEST schrieb Jean Abou Samra:
> Le vendredi 28 juillet 2023 à 10:57 +0300, Lib Lists a écrit :
> > The solution was to build the tuplet number text as a markup.
> > I wonder if there is a way to specify the alignment of the tuplet
> > number with the tuplet bracket instead of specifying paddings and
> > offsets as I did.
> 
> This already looks somewhat better:
> 
> 
> 
> ```
> \version "2.25.7"
> 
> \new Staff
> {
>   \relative c'
>   \repeat unfold 5 {
>     \override TupletBracket.outside-staff-priority = #0
>     \override TupletBracket.bracket-visibility = ##t
>     \tuplet 5/4 {
>       \override TupletNumber.text = \markup {
>         \concat {
>           "5:4"
>           \magnify #0.5
>             \general-align #Y #DOWN
>               \override #'(baseline-skip . 0)
>                 \column { "5" \rhythm { 8 } }
>         }
>       }
>       \override TupletBracket.padding = #0
>       \override TupletNumber.Y-offset = #1.5
>       \tuplet 5/4 {  c8[ c c c c]  }
>     }
>   }
> }
> ```
> 
> Best,
> 
> Jean

Attachment: custom-tuplet-text.ly
Description: Text Data

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


reply via email to

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