Как аннотировать нотоносцы номерами ударов в Lilypond?

Я хотел бы аннотировать RhythmicStaff номерами ударов, как показано на следующем рисунке:RhythmicStaff с номерами битов под нотоносцем

Возможно, можно было бы использовать символ '_' после ноты для добавления чисел, связанных с нотой в начале доли, но как насчет пустых долей - там, где нет ни ноты, ни паузы, а долю все же нужно показать - как последние меры в примере изображения.

Каким будет правильный способ сделать это? В идеале, чтобы каждый такт, каждый такт в партитуре автоматически аннотировался номерами долей в нужных местах?

Ответы (2)

Какой-то способ получить это автоматически:

#(define (контекст Beat_counter_engraver)
   (let ((measpos #f) (grouping #f) (basemom #f) (beatmom #f))
     (определить (мама-> давняя мама)
       (пусть((пара (момент->дробная мама)))
         (/ (пара автомобилей) (пара cdr))))
     (определить (является ли бит-моментом? подсчитать количество ударов gping)
       (if (= (* count (mom->dur basemom)) (mom->dur measpos))
           (+ 1 бит)
           (if (> (* count (mom->dur basemom)) (mom->dur measpos))
               (если (ноль? gping)
                   (is-beat-moment? (+ count (car gping)) (cdr gping) (+ 1 beatcount)))))
     (мастер-гравер
       ((процесс-музыкальный гравер)
          (set! measpos (ly: context-property context 'measurePosition 'noof))
          (установить! группировка (ly:context-property контекст 'beatStructure' noof))
          (установить! basemom (ly: context-property context 'baseMoment' noof))
          (set! beatmom (is-beat-moment? 0 группировка 0))
          (если битмама
            (let ((grob (ly:engraver-make-grob engraver 'TextScript'())))
                  (ly:grob-set-property! grob 'текст (число->строка beatmom))
                  (ly: grob-set-property! grob 'направление ВНИЗ)
                  (ly:grob-set-property! grob 'заполнение 3)))))))

\макет {
  \контекст {
    \RhythmicStaff
    \состоит из #Beat_counter_engraver
  }
}

\new Ритмический посох
{
  \set RhythmicStaff.baseMoment = #(ly:make-moment 1 16) % вручную убедитесь, что базовый момент равен 1/16
  \set RhythmicStaff.beatStructure = 3,3,3,3 % вручную убедитесь, что доли всегда имеют 3 16-й
  \время 6/16
  16 16 16 16 16 16|
  р16 16 16 8.
  \время 3/16
  16[ \once\set стебельRightBeamCount = 1
      \один раз\установить стебельлевефтбеамкаунт = 1
       р16 16]
  \время 6/16
  16 16 р р8. \бар "|."
}


%% с разными моментами:

\ новый ритмический посох {
  \ время 2/4
  8 16 16 8 16 16
  \ время 3/8
  16 16 16 16 16 16
  \время 6/8
  8 16 16 8 16 16 16 16 16 16
  \ время 9/7 \ туплет 7/8 { 8 8 8 8 8 8 8 8 8 }
}

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

Одна проблема здесь заключается в том, что это работает только тогда, когда это какое-то событие в такте, поэтому, если у вас есть что-то вроде \time 4/4 8 4 8, это ничего не выведет на второй бит, так как там ничего нет. Итак, вы можете сделать что-то вроде

<< \music \repeat unfold #(floor (/ (/ (car (moment->fraction (ly:music-length music))) (cdr (moment->fraction (ly:music-length music)))) 1/16)) s16 >>

РЕДАКТИРОВАТЬ: Чтобы добиться чего-то вроде вашего примера, вы также можете сделать что-то вроде этого:

#(define (контекст Beat_counter_engraver)
   (let ((measpos #f) (grouping #f) (basemom #f) (beatmom #f))
     (определить (мама-> давняя мама)
       (пусть((пара (момент->дробная мама)))
         (/ (пара автомобилей) (пара cdr))))
     (определить (является ли бит-моментом? подсчитать количество ударов gping)
       (if (= (* count (mom->dur basemom)) (mom->dur measpos))
           (+ 1 бит)
           (if (> (* count (mom->dur basemom)) (mom->dur measpos))
               (если (ноль? gping)
                   (is-beat-moment? (+ count (car gping)) (cdr gping) (+ 1 beatcount)))))
     (мастер-гравер
       ((процесс-музыкальный гравер)
          (set! measpos (ly: context-property context 'measurePosition 'noof))
          (установить! группировка (ly:context-property контекст 'beatStructure' noof))
          (установить! basemom (ly: context-property context 'baseMoment' noof))
          (set! beatmom (is-beat-moment? 0 группировка 0))
          (если битмама
            (let ((grob (ly:engraver-make-grob engraver 'TextScript'())))
                  (ly:grob-set-property! grob 'текст (число->строка beatmom))
                  (ly:grob-set-property! grob 'направление ВНИЗ)))))))

\макет {
  \контекст {
    \Динамика
    \состоит из #Beat_counter_engraver
    \override TextScript.font-shape = ##f
    \override TextScript.Y-смещение = #-0.8
    \ состоит Instrument_name_engraver
  }
}

шестнадцатая сетка во время =
#(define-music-function (m) (ly:music?)
   #{
     \repeat unfold #(floor (/ (/ (car (момент->фракция (ly:музыка-длина м))) (cdr (момент->фракция (ly:музыка-длина м)))) 1/16)) с16
   #})

\бумага {
  рваный-последний = ##f
}

мусI = {
  \отметить "В 3"
  \ время 3/8
  8 8 16 р |
  8 16 16 8 |
  16[ 16 8 р16 16] |
  4. \бар "|."
}

>

mus II = {
  \отметить "В 4"
  \время 4/8
  \set Score.beatStructure = 1,1,1,1
  8 16 16~ 8 r8 |
  r16 16[ r16 16] r16 8.~ |
  4 ~ 16 8 16 |
  16 r16 4 r8 \bar "|."
}

>

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

Что означает слово «ленивый»?
Многому предстоит научиться в этом посте — я вижу, что lilypond использует форму Scheme.
Спасибо за подробный ответ. В этом посте нужно многому научиться. Я вижу, что lilypond использует форму Scheme. Было бы очень полезно, если бы вы добавили абзац, комментирующий и суммирующий то, что делают фрагменты кода - для тех, кто не знаком с языками, подобными lisp. Кроме того, где должно быть размещено определение Beat_Counter_Engraver, чтобы его можно было использовать во всех моих файлах .ly - речь идет о расширении стандартных библиотек схемы lilypond, поэтому может быть отдельный вопрос ...
Чтобы быть точным, lilypond использует реализацию схемы GNU, которая называется guile. Если вы хотите использовать это во всех своих файлах, вы можете поместить такие вещи в отдельный файл Lilypond и использовать \include «путь/к/вашему/файлу» в любом из ваших файлов, которым это может понадобиться. Используя аргумент командной строки -I, вы можете добавлять папки к стандартным путям lilyponds, и frescobaldi отдает предпочтение этому. Таким образом, вы можете использовать псевдоним lilypond для lilypond -I some/path (или, если вы используете Frescobaldi, используйте настройку), поместите все свои включения в этот путь, а затем вы можете просто сделать \include "file" из любого места.
Конечно, вы можете добавить это в scm/scheme-engravers.scm, но это будет означать, что вам нужно будет поддерживать свою собственную версию lilypond, и вы маскируете, что ваш файл нуждается в нестандартных вещах. Таким образом, использование include - довольно хороший способ сделать это. Я собираюсь добавить некоторые пояснения к тому, что здесь делается позже, но в основном это определяет новый гравер (то есть, по сути, набор слушателей и обработчиков событий, которые делают такие вещи, как создание графических объектов).
@saraf Этот новый гравер в основном ничего не делает, кроме как проверяет, находимся ли мы в данный момент в такте, и если да, он возвращает количество битов в текущем такте.

Пытаться

<<
  \new RhythmicStaff
  {
    \repeat volta 2 {
      \tempo "in 3"
      \time 3/8
      8 8 16 r |
      8 16 16 8 |
      16[ 16 8 r16 16] |
    }
    \repeat volta 2 {
      \tempo "in 4"
      \time 4/8
      8 16 16~8 r |
      r16 16[ r16 16] r16 8.~ |
      4~16 8 16 |
      16 r16 4 r8 |
    }
  }
  \new Lyrics \lyricmode {
    \repeat unfold 3 { "1"8 "2" "3" | }
    \repeat unfold 4 { "1" "2" "3" "4" | }
  }
>>

выход

Основная уловка здесь заключается в использовании Lyricsбез \addlyricsили \lyricsto, что позволяет вам явно указать продолжительность: "1"8это слог "1"с продолжительностью 8, и эта продолжительность затем используется по умолчанию для всего остального.