Hello Kieren,
first of all: Looks like a nice piece!
Second: offtopic nitpicks. There are some superfluous LyricExtenders
there – I’d rather leave them out if they are very short.
(<http://sourceforge.net/p/testlilyissues/issues/4509/> …) And note the
mid-air bar-numbers, where they are aligned with ScoreMarks. I’d move
Bar_number_engraver to the topmost staff. And I like for long syllables
to be increasingly left-aligned, for which I wrote a custom grob callback.
And finally on your actual point, an answer which is probably not the
one you wanted to hear: :-)
I’d vote to keep with four staves, at least in this example. My model
for engraving choral scores is the respective volume in the 1926
Breitkopf & Härtel Brahms complete edition. It’s beautiful and excellent
to read. It always uses a consistent number of staves for the music
(which might also be due to the music), which I think gives more
consistent looks and takes some difficulty (in finding the staff he
should be singing from) from the singer. The other major point is that
it doesn’t print ‘redundant’ lyrics, i.e. passages with equal rhythm and
wording in multiple voices have the lyrics printed only once, mostly
below the topmost of the staves. This is certainly a controversial
feature, but IMO the clarity it adds to the score and the nudge to not
only read one’s own voice are valuable, alongside with the gain on
vertical space.
For this I also wrote a nice, easy-to-use solution, which you find
applied to the version in the attachment.
Of course there are cases where one needs to go e.g. to eight staves, or
have other changes in staff number – the best of orchestral score
engravings show it. It _would_ of course be great to have a good
mechanism for that in LilyPond, but it looks like a really involved task.
Other measures to obtain closer vertical spacing are shifting dynamics
(a task for which I haven’t yet found a definite, if only personal
solution yet – very complicated) – and narrower hairpins (My default
stylesheet has \override Hairpin.height = 0.45).
I hope there is something useful for you amongst these ideas…
Yours, Simon
On 24.11.2015 16:14, Kieren MacMillan wrote:
Hello list,
I’ve posted this question several times before, but the discussion always got
truncated or derailed… I’m hoping this time we can work this through to a
solution.
Choral pieces tend to have both sections of polyphony (requiring 4 or more
staves) and sections of homophony (requiring as few as 1 staff). I want to be
able to arbitrarily break systems and have Lilypond Do The Right Thing™, by
which I mean use the maximum number of systems when necessary, but combine
voices and lyrics to 3 or 2 staves or even 1 staff where possible.
Bonus points if we can convince Lily to automagically [e.g., via an engraver?]
put a user-definable markup indicating who is singing at a given moment, add
splitting-or-combining arrows at the end(s) of systems, etc.
I’ve attached the first 17 measures of one of my original carols as an example
we can work with/through. Is anyone out there willing to work with me to find
the Best Practice here? I’m happy to do this on-list or off-, as appropriate.
Thanks,
Kieren.
________________________________
Kieren MacMillan, composer
‣ website: www.kierenmacmillan.info
‣ email: i...@kierenmacmillan.info
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user
\version "2.19.31"
\language "english"
\include "interpolate.ily"
\include "switch-lyrics.ily"
#(set-global-staff-size 15.5)
\paper {
page-count = 2
system-count = 5
ragged-bottom = ##t
ragged-last-bottom = ##t
system-system-spacing = #'((minimum-distance . 18) (padding . 8))
}
\layout {
\context {
\Voice
\consists "Melody_engraver"
\override Stem #'neutral-direction = #'()
}
\context {
\Staff
\name ChoralStaff
\alias Staff
\override DynamicLineSpanner.direction = #UP
\override Script.direction = #UP
\override TextScript.direction = #UP
\override TupletBracket.direction = #UP
\override TupletNumber.direction = #UP
}
\context {
\ChoirStaff
\accepts ChoralStaff
}
\context {
\type "Engraver_group"
\name ScoreMarks
\consists "Staff_collecting_engraver"
\consists "Axis_group_engraver"
\override VerticalAxisGroup.staff-affinity = #DOWN
\override VerticalAxisGroup.nonstaff-relatedstaff-spacing =
#'((basic-distance . 1) (minimum-distance . 1) (padding . 2) (stretchability . 0))
\override VerticalAxisGroup.nonstaff-unrelatedstaff-spacing =
#'((basic-distance . 6) (minimum-distance . 6) (padding . 4) (stretchability . 0))
\override VerticalAxisGroup.nonstaff-nonstaff-spacing =
#'((basic-distance . 1) (minimum-distance . 1) (padding . 1) (stretchability . 0))
\consists "Metronome_mark_engraver"
\override MetronomeMark.font-size = #2
\override MetronomeMark.font-series = #'normal
\override MetronomeMark.Y-offset = ##f
\override MetronomeMark.padding = #2
\override MetronomeMark.break-align-symbols = #'(time-signature key-signature)
\override MetronomeMark.non-break-align-symbols = #'(paper-column-interface)
\consists "Text_spanner_engraver"
\override TextSpanner.font-size = #2
\consists "Mark_engraver"
\override RehearsalMark.Y-offset = ##f
\override RehearsalMark.outside-staff-priority = #75
\override RehearsalMark.font-size = #2
\override RehearsalMark.break-align-symbols = #'(time-signature key-signature)
\consists "Time_signature_engraver"
\override TimeSignature.stencil = #point-stencil
}
\context {
\Score
\remove "Metronome_mark_engraver"
\remove "Mark_engraver"
\remove "Bar_number_engraver"
\accepts ScoreMarks
\override TimeSignature.style = #'()
\override BarNumber.font-size = #2.5
\override BarNumber.padding = #2
}
}
%%%% GLOBAL %%%%
\header {
title = "Witherâs Carol"
}
WithersCarol_global = {
%% v. 1
\key d \major
\tempo "Brightly" 4=108
\time 2/4
\omitLyrics #'(alt ten bass)
\partial 8 s8
s4*2
\time 4/4
s4*4
\time 2/4
s4*2*3
\time 4/4
s4*4
\time 2/4
s4*2*2
\time 7/8
\showLyrics #'(bass) % () to prevent interpretation as a drum noteâ¦
s8*7
\time 2/4
s4*2
\time 4/4
\tempo \markup "Relaxing slightly"
s1*2
\tempo "Like a madrigal" 4=80
\showLyrics #'(alt ten)
s1
\time 9/8
s8*9
\time 4/4
s2
\tempo \markup "poco rit."
s1
\tempo \markup "regain tempo"
s4 \omitLyrics #'(alt ten bass) s4
s1
\bar "||"
}
%%%% VOICES %%%%
WithersCarol_soprano_notes = {
%% v. 1
a8\mf | % sop 0
d'8 d' d'16( e') fs'( g') | % sop 1
a'8 a' b'2\tenuto r8 a' | % sop 2
fs'8 d' e' cs' | % sop 3
d'4 d'8 a | % sop 4
d'8 d' d'16( e') fs'( g') | % sop 5
a'8 a' b'2\tenuto r8 r16 a' | % sop 6
fs'8 d' e'16( d') cs'8 | % sop 7
d'4 d' | % sop 8
r8 d''4\f-> b'8 b'4-> a'16 d'' | % sop 9
b'8 b' a'4 | % sop 10
r8 a'4 fs'8 fs'4 e' | % sop 11
d'4 b'8 b'8\> ~ 2 | % sop 12
r2\! r4 fs'8(\p gs') | % sop 13
a'2.\< e''4.\! | % sop 14
d''8 fs'' e''-! r cs'' d''\tenuto ~ 4 ~ | % sop 15
d''2 ~ 4\> r8\! r16 g'\pp | % sop 16
fs'8 d' e'16( d') cs'8 d'4 d' | % sop 17
}
WithersCarol_soprano_lyrics = \lyricmode {
%% v. 1
So now is come our joy -- fulâst feast,
Let evâ -- ry one be jol -- ly.
Each room with i -- vy __ leaves is drest,
And evâ -- ry post with hol -- ly.
Though some churls at our mirth re -- pine.
Round your fore -- heads gar -- lands twine.
Drown sor -- row in a cup of wine. __
And let us all __ be mer -- ry.
}
WithersCarol_alto_notes = {
%% v. 1
a8\mf | % alto 0
d'8 d' d'16( e') fs'( g') | % alto 1
a'8 a' b'2\tenuto r8 a' | % alto 2
fs'8 d' e' cs' | % alto 3
d'4 d'8 a | % alto 4
d'8 d' d'16( e') fs'( g') | % alto 5
a'8 a' b'2\tenuto r8 r16 a' | % alto 6
fs'8 d' e'16( d') cs'8 | % alto 7
d'4 d' | % alto 8
r8 fs'4\f-> a'8 g'4-> e'16 fs' | % 9
g'16( fs') e'8 fs'4 | % 10
r8 e'4 cs'8 b4 cs' | % 11
b4 a8 a\> ~ 2 | % 12
r2\! d'2\p | % 13
cs'4.(\< e'4 fs'8) g'4.\! | % 14
fs'4 g' g'8-! r g' a'\tenuto ~ | % 15
a'2 ~ 4\> r8\! r16 g'\pp | % 16
fs'8 d' e'16( d') cs'8 d'4 d' | % alto 17
}
WithersCarol_alto_lyrics = \lyricmode {
%% v. 1
So now is come our joy -- fulâst feast,
Let evâ -- ry one be jol -- ly.
Each room with i -- vy __ leaves is drest,
And evâ -- ry post with hol -- ly.
Though some churls at our mirth re -- pine.
Round your fore -- heads gar -- lands twine.
Drown sor -- row in a cup of wine. __
And let us all __ be mer -- ry.
}
WithersCarol_tenor_notes = {
\clef "treble_8"
%% v. 1
a,8\mf | % ten 0
d8 d d16( e) fs( g) | % ten 1
a8 a b2\tenuto r8 a | % ten 2
fs8 d e cs | % ten 3
d4 d8 a, | % ten 4
d8 d d16( e) fs( g) | % ten 5
a8 a b2\tenuto r8 r16 a | % ten 6
fs8 d e16( d) cs8 | % ten 7
d4 d | % ten 8
r8 d'4\f-> b8 b4-> a16 d' | % ten 9
b8 b a4 | % ten 10
r8 a4 fs8 fs4 e | % ten 11
e4 d8 d\> ~ 2 | % ten 12
r4\! e\p fs2 ~ | % ten 13
<< { fs4. cs'2. } { s4.\< s s\! } >> | % ten 14
b16 cs' d'8-! r cs' d'2\tenuto ~ | % ten 15
d'2 ~ 4\> r8\! r16 g\pp | % ten 16
fs8 d e16( d) cs8 d4 d | % ten 17
}
WithersCarol_tenor_lyrics = \lyricmode {
%% v. 1
So now is come our joy -- fulâst feast,
Let evâ -- ry one be jol -- ly.
Each room with i -- vy __ leaves is drest,
And evâ -- ry post with hol -- ly.
Though some churls at our mirth re -- pine.
Round your fore -- heads gar -- lands twine.
Drown sor -- row in a cup of wine. __
And let us all __ be mer -- ry.
}
WithersCarol_bass_notes = {
\clef bass
%% v. 1
a,8\mf | % bass 0
d8 d d16( e) fs( g) | % bass 1
a8 a b2\tenuto r8 a | % bass 2
fs8 d e cs | % bass 3
d4 d8 a, | % bass 4
d8 d d16( e) fs( g) | % bass 5
a8 a b2\tenuto r8 r16 a | % bass 6
fs8 d e16( d) cs8 | % bass 7
d4 d | % bass 8
d4.->\f d8 d4-> d8 | % bass 9
d2 | % bass 10
fs4. e8 d4 d | % bass 11
g,4 g,8 g,\> ~ 8 r a,4 | % bass 12
b,1\p ~ | % bass 13
b,2. ~ 8.\< d16 e fs | % bass 14
a8-!\! r a b\tenuto ~ 2 ~ | % bass 15
b2 ~ 4\> r8\! r16 g\pp | % bass 16
fs8 d e16( d) cs8 d4 d | % bass 17
}
WithersCarol_bass_lyrics = \lyricmode {
%% v. 1
So now is come our joy -- fulâst feast,
Let evâ -- ry one be jol -- ly.
Each room with i -- vy __ leaves is drest,
And evâ -- ry post with hol -- ly.
Though some churls re -- pine.
Round your fore -- heads gar -- lands twine. __
Drown sor -- row in a cup of wine. __
And let us all __ be mer -- ry.
}
\score {
<<
\new ScoreMarks \WithersCarol_global
\new ChoirStaff <<
\new ChoralStaff = "Staff_soprano" \with { \consists "Bar_number_engraver" }
\new Voice = "Voice_soprano" << \WithersCarol_global \WithersCarol_soprano_notes >>
\new Lyrics = sopLyrics \lyricsto "Voice_soprano" \WithersCarol_soprano_lyrics
\new ChoralStaff = "Staff_alto"
\new Voice = "Voice_alto" << \WithersCarol_global \WithersCarol_alto_notes >>
\new Lyrics = altLyrics \lyricsto "Voice_alto" \WithersCarol_alto_lyrics
\new ChoralStaff = "Staff_tenor"
\new Voice = "Voice_tenor" << \WithersCarol_global \WithersCarol_tenor_notes >>
\new Lyrics = tenLyrics \lyricsto "Voice_tenor" \WithersCarol_tenor_lyrics
\new ChoralStaff = "Staff_bass"
\new Voice = "Voice_bass" << \WithersCarol_global \WithersCarol_bass_notes >>
\new Lyrics = bassLyrics \lyricsto "Voice_bass" \WithersCarol_bass_lyrics
>>
>>
}
\version "2.19.25"
#(define (lyric-text::interpolate-alignment grob)
(let*
((width (cdr (ly:grob-property grob 'X-extent)))
(lower-threshold 3)
(upper-threshold 11)
(maximum (- 4/5))
;; calculate parameters for use in the ‘sigmoid’ cubic function with
;; (sigmoid lower-threshold) --> 0
;; (sigmoid upper-threshold) --> maximum
;; and zero ‘slope’ in both these points, i.e. a smooth transition between
;; constants and interpolation
(a (/ (* 2 maximum)
(+ (- (expt upper-threshold 3))
(* 3 upper-threshold upper-threshold lower-threshold)
(* -3 upper-threshold lower-threshold lower-threshold)
(expt lower-threshold 3))))
(b (/ (- maximum (* a (+ (expt upper-threshold 3)
(* 2 (expt lower-threshold 3))
(* -3 upper-threshold (expt lower-threshold 2)))))
(expt (- upper-threshold lower-threshold) 2)))
(c (/ (- maximum
(* b (- (expt upper-threshold 2) (expt lower-threshold 2)))
(* a (- (expt upper-threshold 3) (expt lower-threshold 3))))
(- upper-threshold lower-threshold)))
(d (- maximum
(* upper-threshold c)
(* (expt upper-threshold 2) b)
(* (expt upper-threshold 3) a)))
(sigmoid (lambda (x) (+ (* a x x x) (* b x x) (* c x) d))))
;(format #t "The four parameters have been determined as: \n a ~a \n b ~a
\n c ~a \n d ~a\n" a b c d)
(cond
((<= width lower-threshold) 0)
((< lower-threshold width upper-threshold)
(sigmoid width))
((>= width upper-threshold) maximum))))
\layout {
\context {
\Lyrics
\override LyricText.self-alignment-X = #lyric-text::interpolate-alignment
}
}
\version "2.19.25"
%%%%%%%%%%%%%%%%%%% switch lyrics on and off %%%%%%%%%%%%%%%%%%%%%%%%%%%
switchLyrics =
#(define-music-function (fn voices) (procedure? list?)
"
@code{fn} must take a single symbol.
"
(let*
((unfold-voices (lambda (sym) (case sym
((soprano sop) 'sopLyrics)
((sopOne) 'sopOneLyrics)
((sopTwo) 'sopTwoLyrics)
((mezzo mez) 'mezLyrics)
((mezOne) 'mezOneLyrics)
((mezTwo) 'mezTwoLyrics)
((alto alt) 'altLyrics)
((altOne) 'altOneLyrics)
((altTwo) 'altTwoLyrics)
((tenor ten) 'tenLyrics)
((tenOne) 'tenOneLyrics)
((tenTwo) 'tenTwoLyrics)
((baritone bar) 'barLyrics)
((barOne) 'barOneLyrics)
((barTwo) 'barTwoLyrics)
((bass bas) 'bassLyrics)
((bassOne basOne) 'bassOneLyrics)
((bassTwo basTwo) 'bassTwoLyrics))))
(voices (map unfold-voices voices))
(all-lyrics-grobs '(LyricText LyricSpace LyricHyphen LyricExtender))
(tweaks (make-sequential-music (map fn all-lyrics-grobs)))
(direct (lambda (ctx) #{ \context Lyrics = $(symbol->string ctx) $tweaks
#}))
)
(make-sequential-music (map direct voices))))
omitLyrics =
#(define-music-function (voices) (list?)
(let
((omit-single (lambda (grob) (omit (list grob)))))
(switchLyrics omit-single voices)))
hideLyrics = #omitLyrics
showLyrics =
#(define-music-function (voices) (list?)
(let
((show-single (lambda (grob) (undo (omit (list grob))))))
(switchLyrics show-single voices)))
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user