Пользовательская динамическая метка

Я нахожусь в процессе гравировки нот для фортепиано. Написал кастомную динамическую метку — видом которой очень доволен, а вот поведением — не совсем. Это следующее:

mff = \tweak DynamicText.self-alignment-X #LEFT
    #(make-dynamic-script 
    (markup 
        #:dynamic "mf"
        #:normal-text #:italic #:teeny "2ème fois"
        #:dynamic "f"))

При использовании это выглядит так:

измерить с помощью динамического "mf 2éme fois f"

Когда он не используется, он выглядит так:

та же мера без динамики, показывающая разные интервалы

Я доволен тем, что метка начинается ниже заметки, к которой она прикреплена (в отличие от центра ниже этой заметки); но я хотел бы, чтобы он не откладывал следующую ноту до тех пор, пока отметка не будет полностью написана. В идеале это могло бы повлиять на ширину полосы только в том случае, если линия, обозначающая конец полосы, рискует срезать метку.

Я не могу найти то, что я ищу в документации.

Если в этом есть необходимость, вот мой код для музыки:

%% VERSION
\version "2.20.0"

\paper {
    #(include-special-characters)
}
    
mff = \tweak DynamicText.self-alignment-X #LEFT
    #(make-dynamic-script 
    (markup 
        #:dynamic "mf"
        #:normal-text #:italic #:teeny "2ème fois"
        #:dynamic "f"))

%% PIANO UP
pianoUpper = \relative c' {
    \override DynamicLineSpanner.staff-padding = #3
    \clef "treble"
    \key d \minor
    \time 4/4
        
    <\tweak font-size #-3 a f'>4 \f <\tweak font-size #-3 c g'> <f a> <d bes'> | 
    <f a>2 <e g> |
    f2. r4 \bar "||"
    <f a> \mf \< <f a> <f a> <f a>8 <a c> |
    <a c>4. <g bes>8 <f a>4 f \! |
        
    <f a> <f a>8 <e g> <f a>4 <f a>8 <a c> |
    <a c>4. \> <g bes>8 <f a>4 r \! |
    <f a> \p \< <f a> <f a> <f a>8 <a c> |
    <a c>4. <g bes>8 <f a>4 f \! |
    <f a> <f a>8 <e g> <f a>4 <f a>8 <a c> |
        
    <a c>4. \> <g bes>8 <f a>4 r \! |
    \repeat volta 2 {
        c'2\( d8 c bes a |
        bes2 c8 bes a g |
        a2 bes8 a g f |
        g4.\) g8 c,2 \> |
            
        <\tweak font-size #-3 a f'>4 \< <\tweak font-size #-3 c g'> <f a> <d bes'> |
    }
    \alternative { 
        {
            <f a>2 \> <e g>4 r \! | 
        }
        {
            <c a'>2\( <bes g'>\) |
            <a f'>2. r4 \bar "|."
        }
    }
}

%% PIANO LOW
pianoLower = \relative c {
    \clef "bass"
    \key d \minor
    
    f4 c f bes, |
    c2 <c, c'> |
    <f f'>4 c' f, r |
    f' <a c> f <a c> |
    c, <e bes' c> f <a c> | 

    f <a c> f <a c> |
    c, <e bes' c> <f a c> r |
    f <a c> f <a c> |
    c, <e bes' c> f <a c> | 
    f <a c> f <a c> |
        
    c, <e bes' c> <f a c> r |
    f <a c> d, <fis c'> |
    g, <g' bes d> c, <e bes' c> |
    f <a c> d, <f bes> |
    c <e bes c> c <e g> |
        
    f c f bes, |
    c2 c4 c |
    c2 <c, c'> |
    <f f'>4 c' f, r |
}

%% SCORE
\score {
    <<
        \new PianoStaff <<
            \new Staff = "upper" \pianoUpper
            \new Staff = "lower" \pianoLower
        >>
    >>
}
Я думаю , что есть некоторые команды, чтобы переопределить «самовыравнивание» и назначить абсолютную позицию. Я знаю, что сложно найти информацию в документации LilyPond, но, возможно, кто-то найдет ее раньше меня.

Ответы (4)

Вы можете явно установить размер вашей разметки, используя \with-dimensions(или в этом случае, поскольку мы уже находимся в определении макроса схемы, #:with-dimensions. Этот макрос принимает две пары схемы, которые определяют левый и правый, а также нижний и верхний края разметка. Сама разметка может быть больше, чем поле, которое вы определяете с помощью этих мер, и при верстке будет использоваться граница этого поля (дополнительную информацию см. в документации ).

Поскольку \with-dimensionsпринимает только один аргумент, вам необходимо дополнительно обернуть разметку в другой \lineмакрос. Итак, вы можете, например, написать свой макрос следующим образом:

mff = \tweak DynamicText.self-alignment-X #LEFT
    #(make-dynamic-script 
    (markup #:with-dimensions '(0 . 5) '(-3 . 3) #:line 
       (#:dynamic "mf"
        #:normal-text #:italic #:teeny "2ème fois"
        #:dynamic "f")))

Результат:

введите описание изображения здесь

Есть также несколько других способов настройки размеров и выравнивания динамики, некоторые из которых объясняются в этом фрагменте .

Если вы используете это определение, которое выглядит как динамическая метка,

mff= _ \markup { \dynamic mf \italic \teeny "2ème fois" \dynamic f }

то результат такой:

введите описание изображения здесь

«Интерес использования make-dynamic-script вместо обычной разметки заключается в обеспечении вертикального выравнивания объектов разметки». это то, что я могу прочитать в документации: lilypond.org/doc/v2.18/Documentation/notation/… но ваше решение все еще работает в моем конкретном случае. Должен ли я ожидать, что иногда это не так? Как и в других случаях, когда мне нужна длинная пользовательская динамическая метка, и она может не выровняться по вертикали?
После тестов я заметил, что действительно бывают случаи, когда вертикальное выравнивание не соблюдается. Я уже проголосовал за ответ, потому что в этом случае он решил мою проблему (даже если только по счастливой случайности).

На самом деле я только что создал функцию, которая позволила бы мне указать динамический и произвольный текст:

#(define-markup-command
  (staff-expr layout props text)
  (markup?)
  #:properties ((rel-fontsize 0))
  "Creates expression text for a staff.
   
   By default, staff expression text's font is reduced by 0.5
   and is italicized."
  (interpret-markup layout props
   (markup #:line
           (#:with-dimensions '(0 . 0) '(0 . 0)
            (#:fontsize rel-fontsize (#:italic text))))))

staffExpr =
#(define-scheme-function
  (text)
  (markup?)
  #{
    \markup \staff-expr #text
  #}
)

dynExpr = 
#(define-event-function
  (dyn expr) 
  (ly:event? markup?)
  #{
    \tweak DynamicText.self-alignment-X #LEFT
    #(make-dynamic-script
      #{
        \markup \concat {
          #(ly:music-property dyn 'text)
          \pad-x #.75
          \normal-text #expr
        }
      #}
    )
  #}
)

Я, вероятно, мог бы сделать это проще - поскольку я вижу, что было сделано ОП, но я сам довольно новичок в Лилипонде.

В любом случае, вот первые два такта Una Mattina Людовико Эйнауди, где я использовал вышеперечисленные функции:

введите описание изображения здесь

\version "2.22.2"

#(define-markup-command
  (staff-expr layout props text)
  (markup?)
  #:properties ((rel-fontsize 0))
  "Creates expression text for a staff.
   
   By default, staff expression text's font is reduced by 0.5
   and is italicized."
  (interpret-markup layout props
   (markup #:line
           (#:with-dimensions '(0 . 0) '(0 . 0)
            (#:fontsize rel-fontsize (#:italic text))))))

staffExpr =
#(define-scheme-function
  (text)
  (markup?)
  #{
    \markup \staff-expr #text
  #}
)

dynExpr = 
#(define-event-function
  (dyn expr) 
  (ly:event? markup?)
  #{
    \tweak DynamicText.self-alignment-X #LEFT
    #(make-dynamic-script
      #{
        \markup \concat {
          #(ly:music-property dyn 'text)
          \pad-x #.75
          \normal-text #expr
        }
      #}
    )
  #}
)

beamHeight =
#(define-music-function
  (startHeight endHeight)
  (number? number?)
  #{
    \override Beam.positions = #(cons startHeight endHeight)
  #}
)

Props = {
  \numericTimeSignature
  \time 4/4
  \key c \major
  \partial 16
}

RHVoiceOne = {
  \change Staff = "LH" a16~ |
  \stemUp \once \beamHeight #6.25 #6.25 a16 \stemDown \change Staff = "RH" e' a' \stemUp \change Staff = "LH" a \beamHeight #-6.25 #-6.25 \stemDown \change Staff = "RH" e' a' \stemUp \change Staff = "LH" a \stemDown \change Staff = "RH" e' a' \stemUp \change Staff = "LH" a \stemDown \change Staff = "RH" e' a' \once \beamHeight #6.5 #7.5 \stemUp \change Staff = "LH" a \stemDown \change Staff = "RH" e' b' e' |
  \stemUp \change Staff = "LH" \once \beamHeight #6.25 #6.25 a16 \stemDown \change Staff = "RH" e' a' \stemUp \change Staff = "LH" a \beamHeight #-6.25 #-6.25 \stemDown \change Staff = "RH" e' a' \stemUp \change Staff = "LH" a \stemDown \change Staff = "RH" e' \once \beamHeight #-5.75 #-6.25 a'8. \stemUp \change Staff = "LH" b16 \once \beamHeight #7.75 #8.75 c' \stemDown \change Staff = "RH" e' g' b' |
}

Dynamics = {
  \override DynamicText.X-offset = #0.59125 \override DynamicText.Y-offset = #1.75
  % Note the use of \dynExpr that takes a dynamic marking and some text
  s16 | s16 \dynExpr \p \staffExpr legato s16 s8 s4 * 3 | s1 |
}

Sustain = {
  s16 \sustainOn |
  s1 |
  s2 s8 s8\sustainOff s4 |
}

LHVoiceOne = {
  s16 | s1 | s1 |
}

\paper {
  system-system-spacing = #'((basic-distance . 18))
  %annotate-spacing = ##t
  first-page-number = 10
  evenHeaderMarkup = \markup \null
  oddHeaderMarkup = \markup \null
  evenFooterMarkup = \markup {
    \fill-line {
      \center-column {
        \on-the-fly \first-page
        \fromproperty #'header:copyright
        \vspace #1.807
        \null
        \italic
        \on-the-fly \print-page-number-check-first
        \fromproperty #'page:page-number-string
      }
    }
  }
  oddFooterMarkup = \evenFooterMarkup
}
\score {
  \new GrandStaff \with {
  } <<
    \new PianoStaff \with {
      \override StaffGrouper.staff-staff-spacing.basic-distance = #13.65
    } <<
      \new Staff = "RH" \with {
      } <<
        \new Voice = "1" { 
          \Props
          \RHVoiceOne
        }
      >>
      \new Dynamics {
        \Dynamics
      }
      \new Staff = "LH" \with {
      } {
        \clef bass << 
          \new Voice = "1" {
            \Props
            \LHVoiceOne
          }
        >>
      }
      \new Dynamics = "Sustain" \with {
        pedalSustainStyle = #'mixed
        \override PianoPedalBracket.thickness = #1.35
        \override SustainPedalLineSpanner.staff-affinity = #UP
        \override PianoPedalBracket.Y-offset = #-1.6
        \override SustainPedal.X-offset = #-0.75
        \override SustainPedal.Y-offset = #-1.75
      } {
        \Sustain
      }
    >>
  >>
  \layout {
  }
  \midi {
  }
}
В этом случае вы можете рассмотреть возможность использования \whiteoutкоманды.
Собственно, я специально не хотел \whiteoutв данном случае -- так выглядела оригинальная партитура. Кроме того, если бы я не отрегулировал использованную строку (#:with-dimensions...), то текст «выдвинул бы» тактовую черту — но опять же, этого я специально пытался избежать. Но да, если бы я не хотел, чтобы тактовые черты перекрывались (но сохраняя размерность прежней), \whiteoutя бы сделал свое дело!
Лично я, когда заново гравирую кусок, допускаю много вольностей; «исправление» «ошибки» и т. д., я бы, вероятно, переместил этот динамический знак на первую ноту и использовал \whiteoutкоманду для пересечения тактовой черты, потому что это имело бы больше смысла и было бы намного легче читать (для меня). Однако я определенно могу понять, почему вы предпочитаете сделать более точную копию.

Я ничего не знаю о тонкостях LilyPond. Но обычно это просто и достаточно обозначается как mf-f. Будет ли считаться решением то, что вы записываете это таким образом?

Хорошая точка зрения. Мне нравятся решения KISS.