A reciting note is sustained for several syllables.

Normally only the initial reciting tone is printed (and it is printed as a half-note, whole-note, or breve) and the rest of the syllables are printed without notes above them. However, if the number of syllables to be recited is long enough that a line break needs to occur within the recitation, then the reciting tone is repeated at the beginning of the new line. These definitions enable this formatting.

Usage:

\recite 8 g'

The number is the number of syllables to be said on the reciting tone. These syllables are entered as normal in \lyricmode. The note is the pitch for the reciting tone.

\recite g'

When there are no lyrics associated with the recitation tone (as, for example, when printing a psalm tone) then only the pitch of the reciting tone is specified. This usage is for ensuring consistent appearance.

\version "2.24"

#(define (line-position grob)
   "Return position of @var{grob} in current system:
@code{'start}, if at first time-step;
@code{'end}, if at last time-step;
@code{'middle} otherwise."
   (let* ((col (ly:item-get-column grob))
          (ln (ly:grob-object col 'left-neighbor))
          (rn (ly:grob-object col 'right-neighbor))
          (col-to-check-left (if (ly:grob? ln) ln col))
          (col-to-check-right (if (ly:grob? rn) rn col))
          (break-dir-left
           (and
            (ly:grob-property col-to-check-left 'non-musical #f)
            (ly:item-break-dir col-to-check-left)))
          (break-dir-right
           (and
            (ly:grob-property col-to-check-right 'non-musical #f)
            (ly:item-break-dir col-to-check-right))))
     (cond ((eqv? 1 break-dir-left) 'start)
           ((eqv? -1 break-dir-right) 'end)
           (else 'middle))))

#(define (tranparent-at-line-position vctor)
   (lambda (grob)
     "Relying on @code{line-position} select the relevant entry from
@var{vctor}.  Used to determine transparency."
     (case (line-position grob)
       ((end) (not (vector-ref vctor 0)))
       ((middle) (not (vector-ref vctor 1)))
       ((start) (not (vector-ref vctor 2))))))

noteHeadBreakVisibility =
  #(define-music-function (break-visibility)(vector?)
     "Makes notes transparent relying on @var{break-visibility}.
The list of objects to make transparent is taken from @code{hideNotes}."
     #{
       \override NoteHead.transparent =
	 #(tranparent-at-line-position break-visibility)
       \override Dots.transparent =
	 #(tranparent-at-line-position break-visibility)
       \override Accidental.transparent =
	 #(tranparent-at-line-position break-visibility)
       \override Rest.transparent =
	 #(tranparent-at-line-position break-visibility)
       % Stems are always hidden in chant.
       % We assume chants are not in a TabStaff and so don't need to hide
       % TabNoteHeads.
       % Ledger lines have to be taken care of in the layout block using
       % delete-ledgers-for-transparent-note-heads.
     #})

#(define delete-ledgers-for-transparent-note-heads
   (lambda (grob)
     "Reads whether a @code{NoteHead} is transparent.
If so this @code{NoteHead} is removed from @code{'note-heads} from
@var{grob}, which is supposed to be @code{LedgerLineSpanner}.
As a result ledgers are not printed for this @code{NoteHead}"
     (let* ((nhds-array (ly:grob-object grob 'note-heads))
            (nhds-list
             (if (ly:grob-array? nhds-array)
                 (ly:grob-array->list nhds-array)
                 '()))
            ;; Relies on the transparent-property being done before
            ;; Staff.LedgerLineSpanner.after-line-breaking is executed.
            ;; This is fragile ...
            (to-keep
             (remove
              (lambda (nhd)
                (ly:grob-property nhd 'transparent #f))
              nhds-list)))
       ;; TODO find a better method to iterate over grob-arrays, similar
       ;; to filter/remove etc for lists.
       ;; For now rebuilt from scratch.
       (set! (ly:grob-object grob 'note-heads)  '())
       (for-each
        (lambda (nhd)
          (ly:pointer-group-interface::add-grob grob 'note-heads nhd))
        to-keep))))


\layout {
  \context {
    \Staff
    \override LedgerLineSpanner.after-line-breaking =
      #delete-ledgers-for-transparent-note-heads
  }
}

recite =
  #(define-music-function (times note) ((index? 1) ly:music?)
     "Causes @code{note} to be set as a reciting note for @code{times}
syllables.  The value of @code{recite-duration} determines
how the recitation note looks: 1 is a half-note, 0 is a
whole note, and -1 is a breve.  Only the first occurance
of the recitation note and those which appear at the
beginning of a line are visible."
     (let* ((note2 (ly:music-deep-copy note))
	    (recite-duration 0)
	    (recite-multiplier (/ (expt 2 recite-duration) 4)))
       (if (eqv? times 1)
           (withMusicProperty
	    'duration (ly:make-duration recite-duration) note)
           #{ #(withMusicProperty
		'duration (ly:make-duration
			   recite-duration 0 recite-multiplier) note)
             \noteHeadBreakVisibility #begin-of-line-visible
             \repeat unfold #(1- times) {
	       #(withMusicProperty
		 'duration (ly:make-duration
			    recite-duration 0 recite-multiplier) note2)
	       \bar "" }
             \noteHeadBreakVisibility #all-visible
           #})))


% Examples starts here.
\language "english"

global = { \key c \major }

music = {
  \recite 6 g' d' f' g' \bar "|"
}

doxology_words = \lyricmode {
  Glory be to the Father and to the Son
}

\new Staff
<<
  \new Voice = "mel" {
    \cadenzaOn \global \music \bar "||"
    \music \bar "||"
    \music \bar "|."
  }
  \new Lyrics \lyricsto "mel" {
    \doxology_words
    \doxology_words
    \doxology_words
  }
>>