Набор современной музыки в LilyPond

в 11:23, , рубрики: lilypond, типографика, метки:

Однажды я уже рассказывал, что такое LilyPond, и с чем его едят. Обещания написать простую статью я, к сожалению, пока выполнить не смог, зато собрался описать, как я набирал ужасающий нотный пример из музыки Н. Корндорфа
Набор современной музыки в LilyPond
(«Welcome!» для шести женских голосов)


Какие сложности здесь есть?

  • Разные темпы на разных станах
  • Разное количество длительностей на одно и то же время
  • Составной размер
  • Несовпадение тактовых черт

Для решения первой задачи нужно заглянуть в справочник по внутренностям. Там написано, что контекст Score содержит в себе отвечающий за отображение обозначения темпа Metronome_mark_engraver. Следующие строки переносят его в контекст Staff (нотного стана), позволяя написать разные темпы на разных строчках (и не только).

layout {
  context {
    Score
    remove "Timing_translator"
    remove "Default_bar_line_engraver"
    remove "Metronome_mark_engraver"
    ...
  }
  context {
    Staff
    consists "Timing_translator"
    consists "Default_bar_line_engraver"
    consists "Metronome_mark_engraver"
  }
  ...
}

Также здесь из контекста партитуры в контекст стана переносятся Default_bar_line_engraver и Timing_translator, отвечающие за тактовые черты и соблюдение размера (к третьему пункту).

Вторая проблема решается с помощью масштабирования длительностей. Команда scaleDurations изменяет длительности в указанном соотношении. Порядок аргументов (такой же как у команды times, создающий триоли, квартоли, квинтоли и другие мультиоли [англ: tuplet] ), я запомнил так: вместо 88 — 80. Я специально не сокращал дробь, поскольку она соответствует соотношению темпов (пример: второй стан).

scaleDurations #'(88 . 80)
{
  relative c' {
    f4repeatTie ( g2) g4 ~ g8. g16 ( ~ g4 ~ g8. fis16 ~ fis4 fis8 g ~ g4 |
    ...
  }
  addlyrics {
  _ la ka ma na pa ra sa 
  }
}

С размерами и тактовыми чертами я поступил следующим образом. Во-первых, в версии 2.15 (вот-вот выйдет стабильный 2.16) появилась простая команда compoundMeter, с помощью которой можно нарисовать тактовый размер с плюсиками. Но простое использование этой команды не даст нам желаемого эффекта: в таком случае размер такта будет равен сумме всех компонентов, а здесь же нужно разделить их тактовыми чертами. На помощь приходит ручная установка размера такта (пример: первый стан).

compoundMeter #'((11 4) (11 4) (11 4) (11 4))
set Timing.measureLength = #(ly:make-moment 11 4)

С третьим и шестым станами сложнее: у них компоненты не равны (пример: третий стан).

compoundMeter #'((9 4) (3 4) (6 4) (6 4) (3 4) (9 4))
tempo 4 = 72
relative c' {
  dynamicUp
  scaleDurations #' (88 . 72)
  {
    set Timing.measureLength = #(ly:make-moment 11 4)
    e8.repeatTie ( f16 ~ f4 ~f8 e ~ e4 dis4 ~ dis8. e16 ~ e4 ~ e8.) e16~ ( e4 |
    set Timing.measureLength = #(ly:make-moment 11 12)
    e8 f ~ f4 e ~ |
    set Timing.measureLength = #(ly:make-moment 11 6)
    e8. dis16 ~ dis4 dis16 e8. ~ e4) e2
    once override Staff.BarLine #'allow-span-bar = ##f
    set Timing.measureLength = #(ly:make-moment 11 6)
    e4~( e8. dis16 ~ dis4 ~ dis8 e8 ~ e4 dis4 ~ |
    set Timing.measureLength = #(ly:make-moment 11 12)
    dis8. e16 ~ e4 ~ e8.) e16~ |
    set Timing.measureLength = #(ly:make-moment 11 4)
    e4 ~ e8 e8mp<~( e4 dis ~ dis8. e16 ~ e4 ~ e8. ) f16->mf~f4 ~ f8 f8~ | bar "||"
    f4
  }
}

Здесь в каждом новом такте устанавливается свойство Timing.measureLength в соответствующую величину. Функция #(ly:make-moment) создаёт определённую длительность. Внимание: внутри scaleDurations-блока размеры тактов должны всё равно исчисляться по глобальному времени: отсюда размеры 11/4, 11/6 и 11/12. Кроме того, единократное (once) изменение свойства allow-span-bar запрещает соединять эту тактовую черту с ещё одной на пятом стане. В этом же месте такая же конструкция прописана и на четвёртом стане.

В чём отличие set от override
Команда set управляет свойствами контекста, а override — свойстами грóбов (grob = graphical object). Также существует команда tweak, изменяющая свойства у непосредственно следующего объекта, его тип даже не обязательно указывать. Вариант once override переопределяет свойство только на одно использование (но не обязательно следующее непосредственно за данной командой)

Косметические изменения включали в себя уменьшение параметра spacing-increment (увеличение расстояния между нотами относительно базового при удвоении их длительности) с дефолтного 1,2 но 0
,5 и изменение шрифта и размера текста:

layout {
    ...    
    override SpacingSpanner #'spacing-increment = #0.5
  }
  ...
  context {
    Lyrics
    override LyricText #'font-name = #"Century"
    override LyricText #'font-size = #3
  }
}

С удовольствием разъясню ещё какие-нибудь нюансы набора, если будут непонятны.

Исходный код: pastebin.com/EXsYRQzg
Скачать последнюю unstable-версию: lilypond.org/development.html (на 2.14 работать не будет).

Автор: m03r


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js