Easy Gregorian notation

This snippet shows a special notation for easy Gregorian music.

Let's assume that the LilyPond code below is stored as modernGregorian.ily as indicated. The syntax is then as follows.

\include "modernGregorian.ily"

...

\cadenzaOn
\omit Stem
note ...
\melisma { \lst note \mli note \sli note \tli note }

where

  • \lst goes for long stem
  • \mli goes for medium ligature
  • \sli goes for short ligature
  • \tli goes for teeny ligature

It also includes a simple ornament

note -\tweak extra-offset #'(X . Y) \orn

Known issues:

  • modernGregorian.ily does not support MIDI output.
  • \melisma does not follow key signatures.

\version "2.24"

% => https://lists.gnu.org/archive/html/lilypond-user/2015-01/msg00709.html
% => https://lists.gnu.org/archive/html/lilypond-user/2015-01/msg00823.html

%% Works with other sizes:
%#(set-global-staff-size 25)
%#(set-global-staff-size 16)

%%%%% Defs to be saved as "modernGregorian.ily" %%%%%%%%%

%%%% Defining new stem/ligatures:
% long stem
lst = #(define-music-function (mus)
     (ly:music?)
   #{
     \stemDown
     \undo\omit Stem
     \once\override Stem.length = #7
     \once\override Stem.X-extent = #'(.1 . 0)
     \once\override NoteHead.stem-attachment = #'(-1.5 . -.1)
     $mus
     \omit Stem
   #})

%long curved ligature
#(define (long-curved-ligature grob)
   (if (ly:stencil? (ly:stem::print grob))
     (let* ((stencil (ly:stem::print grob))
            (X-ext (ly:stencil-extent stencil X))
            (Y-ext (ly:stencil-extent stencil Y))
            (width (interval-length X-ext))
            (len (interval-length Y-ext)))
       (ly:stencil-translate
         (grob-interpret-markup grob
           (markup
             (#:path width
               (list (list (quote moveto) -0.7 -0.65)
                   (list (quote curveto) -1.2 -0.4 -1.1 -0.2 -0.9 0.5)
                   (list (quote curveto) -0.9 0.5 -0.4 2 -0.8 2.2)))))
         (cons 0 (interval-start Y-ext))))
     #f))

lli = #(define-music-function (mus)
     (ly:music?)
        #{
          \stemUp
          \undo\omit Stem
          \override Stem.stencil = #long-curved-ligature
          $mus
          \omit Stem
        #})

%medium curved ligature
#(define (medium-curved-ligature grob)
   (if (ly:stencil? (ly:stem::print grob))
     (let* ((stencil (ly:stem::print grob))
            (X-ext (ly:stencil-extent stencil X))
            (Y-ext (ly:stencil-extent stencil Y))
            (width (interval-length X-ext))
            (len (interval-length Y-ext)))
       (ly:stencil-translate
         (grob-interpret-markup grob
           (markup
             (#:path width
               (list (list (quote moveto) -0.7 -0.65)
                   (list (quote curveto) -1.2 -0.4 -1.1 -0.2 -0.9 0.5)
                   (list (quote curveto) -0.9 0.5 -0.4 1.9 -1.4 1.8)))))
         (cons 0 (interval-start Y-ext))))
     #f))

mli = #(define-music-function (mus)
     (ly:music?)
        #{
          \stemUp
          \undo\omit Stem
          \override Stem.stencil = #medium-curved-ligature
          $mus
          \omit Stem
        #})

%short curved ligature
#(define (short-curved-ligature grob)
   (if (ly:stencil? (ly:stem::print grob))
     (let* ((stencil (ly:stem::print grob))
            (X-ext (ly:stencil-extent stencil X))
            (Y-ext (ly:stencil-extent stencil Y))
            (width (interval-length X-ext))
            (len (interval-length Y-ext)))
       (ly:stencil-translate
         (grob-interpret-markup grob
           (markup
             (#:path width
               (list (list (quote moveto) -0.7 -0.65)
                   (list (quote curveto) -1.2 -0.4 -1.1 -0.2 -1 0.4)
                   (list (quote curveto) -1 0.4 -0.8 1.5 -1.4 1.3)))))
         (cons 0 (interval-start Y-ext))))
     #f))

sli = #(define-music-function (mus)
     (ly:music?)
        #{
          \stemUp
          \undo\omit Stem
          \override Stem.stencil = #short-curved-ligature
          $mus
          \omit Stem
        #})

%tiny curved ligature
#(define (tiny-curved-ligature grob)
   (if (ly:stencil? (ly:stem::print grob))
     (let* ((stencil (ly:stem::print grob))
            (X-ext (ly:stencil-extent stencil X))
            (Y-ext (ly:stencil-extent stencil Y))
            (width (interval-length X-ext))
            (len (interval-length Y-ext)))
       (ly:stencil-translate
         (grob-interpret-markup grob
           (markup
             (#:path width
               (list (list (quote moveto) -0.7 -0.65)
                   (list (quote curveto) -1.2 -0.4 -1.1 -0.1 -1 0.2)
                   (list (quote curveto) -1 0.2 -0.8 0.7 -1.4 0.6)))))
         (cons 0 (interval-start Y-ext))))
     #f))

tli = #(define-music-function (mus)
     (ly:music?)
        #{
          \stemUp
          \undo\omit Stem
          \override Stem.stencil = #tiny-curved-ligature
          $mus
          \omit Stem
        #})

%% Ornament function
orn = 
  -\tweak self-alignment-X #LEFT
  -\tweak Y-offset #0.5
  -\tweak X-offset #1
  -\tweak outside-staff-priority ##f
  -\markup
      \raise #-.3
      \scale #'(1 . .85)
      \rotate #90 
      \musicglyph "ties.lyric.short"

%% Left aligning lyric :
lal = \once\override LyricText.self-alignment-X = #LEFT

%% horizontal inside staff spacer 
space =
#(define-music-function
     (anzahl)
     (number?)
   #{
     \grace { \repeat unfold #anzahl s }
   #})

% Given some music that represents lyrics, add a prefix to the first
% lyric event.
% syntax is \versus { some lyrics }
% resp. \responsum { some lyrics }
#(define (add-prefix-to-lyrics prefix music)
   (let ((found? #f))
     (map-some-music
      (lambda (m)
	(if found? m
	    (and (music-is-of-type? m 'lyric-event)
		 (begin
		   (set! (ly:music-property m 'text)
			 (string-append prefix (ly:music-property m 'text)))
		   (set! found? #t)
		   m))))
      music)))
% Add unicode 2123 (versicle) as prefix to lyrics.
versus =
#(define-music-function (music) (ly:music?)
   (add-prefix-to-lyrics "℣. " music))
% Add unicode 211F (response) as prefix to lyrics.
responsum =
#(define-music-function (music) (ly:music?)
   (add-prefix-to-lyrics "℟. " music))

%% Defining notelaces (neume, melisma) and dedicated context:
gregorianContext = { 
  \cadenzaOn 
  \omit Clef
  \omit TimeSignature
  \omit StaffSymbol
  \omit Rest
  \omit Flag
  \omit Beam
  \override SpacingSpanner.packed-spacing = ##t
  \override NoteHead.stencil = 
    #(lambda (grob)
       (let ((pos (ly:grob-property grob 'staff-position)))
         (cond ((= pos -6)
             (grob-interpret-markup grob 
               #{
                  \markup
                  \concat { 
                    \with-dimensions #'(0 . 0) #'(0 . 0)
                    \translate-scaled #'(-.45 . 0)
                    \override #'(thickness . 2)
                    \draw-line #'(1.78 . 0)
                    \hspace #-.21 
                    \musicglyph "noteheads.s2" 
                    \hspace #-.25 
                  }
               #}))
           ((= pos -7)
               (grob-interpret-markup grob 
                 #{
                    \markup
                    \concat { 
                      \with-dimensions #'(0 . 0) #'(0 . 0) 
                      \override #'(thickness . 2) 
                      \translate-scaled #'(-.45 . .5)
                      \draw-line #'(1.78 . 0)
                      \hspace #-.21 
                      \musicglyph "noteheads.s2" 
                      \hspace #-.25 
                    }
                 #}))
           ((= pos -8)
               (grob-interpret-markup grob 
                 #{
                    \markup
                    \concat { 
                      \with-dimensions #'(0 . 0) #'(0 . 0) 
                      \override #'(thickness . 2) 
                      \translate-scaled #'(-.45 . 1)
                      \draw-line #'(1.78 . 0)
                      \with-dimensions #'(0 . 0) #'(0 . 0) 
                      \override #'(thickness . 2) 
                      \translate-scaled #'(-.45 . 0)
                      \draw-line #'(1.78 . 0)
                      \hspace #-.21 
                      \musicglyph "noteheads.s2" 
                      \hspace #-.25 
                    }
                  #}))
           (else
              (grob-interpret-markup grob 
                     #{
                        \markup
                        \concat { 
                          \hspace #-.21 
                          \musicglyph "noteheads.s2" 
                          \hspace #-.25 
                        }
                      #})))))
  \override Accidental.extra-offset = #'(-.2 . 0)
  %%% TODO: find a fixed ledger line with no dimension; see
  %%% https://lists.gnu.org/archive/html/lilypond-user/2015-02/msg00681.html
  %\override LedgerLineSpanner.length-fraction = #'() %%% ???
  %\override LedgerLineSpanner.minimum-length-fraction = #'() %%% ???
}

neume = #(define-music-function (mus)
     (ly:music?)
   #{
     \once\override NoteHead.stencil = #(lambda (grob)
         (grob-interpret-markup grob 
           #{
              \markup\concat {
                \hspace #-2
                \score {
                  \transpose c c' { \omit Stem $mus } 
                  \layout {
                    indent = 0
                    ragged-right = ##t
                    \context {
                      \Score
                      \gregorianContext
                    }
                  }
                }
              }
           #}))
   #})

melisma = #(define-music-function (mus)
     (ly:music?)
     #{
        { 
          \once\override Lyrics.LyricText.self-alignment-X = #LEFT
          \neume { $mus } 
          \omit Accidental 
          \omit Dots
          #(make-music
            'NoteEvent
            'pitch
            (ly:make-pitch -1 6 0)
            'duration
            (ly:make-duration 2 0 1))
        }
     #})

% Declare default layout
\layout {
  \context {
    \Score
    \omit TimeSignature
  }
}

%%%%%%%%%%%% end of "modernGregorian.ily" %%%%%%%%%

%%%%%%%%%%% Example %%%%%%%%%%%%%%

%\include "modernGregorian.ily"

\header { tagline = ##f }

allelujaStandard = \transpose c c' {
  \clef G
  \key f\major
  \stemDown
  \omit Stem
  \repeat volta 2 {
    f f \undo\omit Stem <g a> a
    \once\override Staff.BarLine.bar-extent = #'(0 . 2) \bar "|"
    \omit Stem a g \undo\omit Stem <a \tweak extra-offset #'(2.3 . 0) g> 
    \once\override Stem.extra-offset = #'(-1.3 . -.5) <e f>
    \omit Stem g \undo\omit Stem 
    <f \tweak extra-offset #'(2.3 . 0) e> \omit Stem d d 
  }
}

allelujaModern = \transpose c c' {
  \clef G
  \key f\major
  \omit Stem
  \repeat volta 2 {
    f f \melisma {  g \lst a } a 
    \once\override Staff.BarLine.bar-extent = #'(0 . 2) \bar "|"
    a g \melisma { \lst a \tli g } \melisma { \lst e f }
    g \melisma { \lst f \tli e } d d
  }
}

allelujaLyrics = \lyricmode {
  \override LyricHyphen.minimum-distance = #5
  \override LyricSpace.minimum-distance = #5
  A -- le -- lu -- ja.
  \repeat unfold 2 { a -- le -- lu -- ja. }
}

\markuplist {
  \line { \italic "Some simple modern style Gregorian scores can be achieved using the standard" }
  \line { \italic "LilyPond notation although it uses a number of tweaks." }
  \vspace #1
}
\score {
  <<
    \cadenzaOn
    \new Voice = Alleluja \allelujaStandard
    \new Lyrics \lyricsto Alleluja \allelujaLyrics
  >>
  \layout {
    system-count = 1
    ragged-right = ##f
    \context {
      \Lyrics
      \override VerticalAxisGroup.staff-affinity = ##f
    }
  }
  \header {
     piece = \markup { 
      \lower #2.4 \fontsize #8 \bold "551" 
      \column {
        \bold "Alleluja"
        "(ÉE 432)"
      }
    }
  }
}

\markuplist {
  \italic "... but are much easier to code with 'modernGregorian.ily':"
  \vspace #1
}
\score {
  <<
    \cadenzaOn
    \new Voice = Alleluja \allelujaModern
    \new Lyrics \lyricsto Alleluja \allelujaLyrics
  >>
  \layout {
    system-count = 1
    ragged-right = ##f
    \context {
      \Lyrics
      \override VerticalAxisGroup.staff-affinity = ##f
    }
  }
  \header {
   piece = \markup { 
      \lower #2.4 \fontsize #8 \bold "551" 
      \column {
        \bold "Alleluja"
        "(ÉE 432)"
      }
    }
  }
}

zslotar = \transpose c c' {
  \clef G
  \omit Stem
  d d d \melisma { f g \lst a } g -\tweak extra-offset #'(1 . -1) \orn g \melisma { g a \lst c' } 
  a \melisma { \lst a \tli g a \lst c' \mli g \lst a \tli g \tli f }  
  \bar "'" 
  a c' \melisma { \lst c' \tli b \tli a } 
  \bar ""
}

zslotarLyrics = \lyricmode {
  \set stanza = \markup\box\pad-markup #.5 \bold "4b"
  Meg -- is -- mer -- tet -- ted
  vé -- lem, U -- ram az é -- let
}

\markuplist {
  \line { \italic "Now comes a heavier score with some complex neumes..." }
  \line { \italic "Not a problem at all for 'modernGregorian.ily':" }
  \vspace #1
}
\score {
  <<
    \cadenzaOn
    \new Voice = Zslotar \zslotar
    \new Lyrics \lyricsto Zslotar \zslotarLyrics
  >>
  \layout {
    ragged-right = ##f
    \context {
      \Lyrics
      \override VerticalAxisGroup.staff-affinity = ##f
    }
  }
  \header {
    piece = \markup\fontsize #4 { \bold "4b." \normal-text "XV. zsoltár" }
  }
}

sanctus = \transpose c c' {
  \clef G
  \key a\major
  \omit Stem
  \melisma { d \lst e } e 
  \bar "|"
  \melisma { 
    \lst e \sli c \lst d \tli c \tli b, r d \lst f \tli e 
  }
  \melisma { d \lst e } e
  \once\override Staff.BarLine.bar-extent = #'(0 . 2) \bar "|"
  \melisma { e \lst g r a \lst b } \melisma { \lst a \tli g \tli f \tli e }
  \melisma { 
    f \lst a \mli e \sli c \lst d \tli c \tli
    b, -\tweak extra-offset #'(1 . -2.5) \orn 
    r r \lst f \tli e f \lst g 
  } \melisma { \lst f \tli e }
  \bar "||"
}

sanctusLyrics = \lyricmode {
  mi -- ni.
  Ho -- sán -- na in ex -- cél -- sis.
}

\markuplist {
  \line { \italic "... even with ledger lines and neumes' ornament:" }
  \vspace #1
}
\score {
  <<
    \cadenzaOn
    \new Voice = Sanctus \sanctus
    \new Lyrics \lyricsto Sanctus \sanctusLyrics
  >>
  \layout {
    ragged-right = ##f
    \context {
      \Lyrics
      \override VerticalAxisGroup.staff-affinity = ##f
    }
  }
  \header {
    piece = \markup { 
      \fontsize #8 \bold "601" 
      \fontsize #2 
      \raise #2.1 {
        \bold "Sanctus"
        \italic "(GrR VI. mise)"
      }
    }
  }
}