>From 0c05e1385ea9658b32b16aafbedfa10a1e7a041e Mon Sep 17 00:00:00 2001 From: Knut Petersen
Date: Thu, 22 Dec 2016 01:09:07 +0100 Subject: [PATCH] Add automatic lyric extender generation. English documentation updated. TODO: Translations Signed-off-by: Knut Petersen --- Documentation/learning/common-notation.itely | 13 +- Documentation/notation/vocal.itely | 194 +++++++++++---------------- lily/extender-engraver.cc | 6 - lily/lyric-extender.cc | 53 ++++---- ly/music-functions-init.ly | 54 +++++++- scm/define-grob-properties.scm | 12 ++ scm/define-grobs.scm | 5 +- scm/music-functions.scm | 12 +- 8 files changed, 197 insertions(+), 152 deletions(-) diff --git a/Documentation/learning/common-notation.itely b/Documentation/learning/common-notation.itely index b51766c0a2..4ca4cd8374 100644 --- a/Documentation/learning/common-notation.itely +++ b/Documentation/learning/common-notation.itely @@ -1136,8 +1136,9 @@ that should be included in the melisma: If a syllable extends over several notes or a single very long note an @notation{extender line} is usually drawn from the -syllable extending under all the notes for that syllable. It is -entered as two underscores @code{__}. Here is an example from the +syllable extending under all the notes for that syllable. +Lilypond adds extender lines automatically at appropriate places. +Here is an example from the first three bars of @notation{Dido's Lament}, from Purcell's @notation{Dido and Ãneas}: @@ -1151,7 +1152,7 @@ first three bars of @notation{Dido's Lament}, from Purcell's } \addlyrics { When I am laid, - am laid __ in earth, + am laid in earth, } >> @end lilypond @@ -1175,8 +1176,8 @@ far about aligning lyrics to notes. d4 d e | c2 } \addlyrics { - A -- way in a __ man -- ger, - no __ crib for a bed, + A -- way in a man -- ger, + no crib for a bed, } >> @end lilypond @@ -1230,7 +1231,7 @@ example from Handel's @notation{Judas Maccabæus}: c''8 | c8([ bes]) a a([ g]) f | f'4. b, | c4.~ 4 } \addlyrics { - Let flee -- cy flocks the hills a -- dorn, __ + Let flee -- cy flocks the hills a -- dorn, } \relative { \key f \major diff --git a/Documentation/notation/vocal.itely b/Documentation/notation/vocal.itely index 118a58e482..9d5224a4da 100644 --- a/Documentation/notation/vocal.itely +++ b/Documentation/notation/vocal.itely @@ -261,7 +261,7 @@ For more details, see @ref{Automatic syllable durations}. % takes durations and alignment from notes in "one" \new Lyrics \lyricsto "one" { - Life is __ _ love, live __ life. + Life is _ love, live life. } % takes durations and alignment from notes in "one" initially @@ -636,8 +636,8 @@ hyphenated line. This is indicated by placing a double hyphen, Alternatively, when a melisma occurs on the last or only syllable in a word an extender line is usually drawn from the end of the syllable -to the last note of the melisma. This is indicated by placing a -double underscore, @code{__}, immediately after the word. +to the last note of the melisma. Lilypond detects places where extender +lines should be used and adds them automatically. There are five ways in which melismata can be indicated: @@ -656,7 +656,7 @@ together: 8 } \new Lyrics \lyricsto "melody" { - Ky -- ri -- e __ + Ky -- ri -- e } >> @end lilypond @@ -674,7 +674,7 @@ entering lyrics: e8 ( d e2 ) } \new Lyrics \lyricsto "melody" { - Ky -- ri -- e __ + Ky -- ri -- e } >> @end lilypond @@ -736,7 +736,7 @@ to be added to the melisma. e8 d e2 } \new Lyrics \lyricsto "melody" { - Ky -- ri -- _ _ _ e __ _ _ + Ky -- ri -- _ _ _ e _ _ } >> @end lilypond @@ -784,7 +784,7 @@ should be included in the melisma: g8 [ f ] ~ 4 ~ f } \new Lyrics \lyricsto "melody" { - Ky -- ri -- _ e __ _ _ _ + Ky -- ri -- _ e _ _ _ } >> @end lilypond @@ -813,32 +813,9 @@ Notation Reference: Internals Reference: @rinternals{Tunable context properties}. address@hidden -Extender lines under melismata are not created automatically; they -must be inserted manually with a double underscore. - - @node Extenders and hyphens @unnumberedsubsubsec Extenders and hyphens address@hidden melisma address@hidden extender - address@hidden TODO cf Multiple notes to one syllable; should this be merged in? - address@hidden leave this as samp. -gp -In the last syllable of a word, melismata are sometimes indicated with -a long horizontal line starting in the melisma syllable, and ending in -the next one. Such a line is called an extender line, and it is -entered as @samp{ __ } (note the spaces before and after the two -underscore characters). - address@hidden are indicated in the score with extender lines, -which are entered as one double underscore; but short melismata can -also be entered by skipping individual notes, which are entered as -single underscore characters; these do not make an extender line to be -typeset by default.} - @cindex hyphens @c leave this as samp. -gp @@ -854,6 +831,42 @@ distance between two syllables) and the @code{minimum-length} (threshold below which hyphens are removed) properties of @code{LyricHyphen}. address@hidden melisma address@hidden extender + +In the last syllable of a word, melismata are normally indicated with +a long horizontal line starting in the melisma syllable, and ending in +the next one. Such a line is called an extender line, and it is +added automatically. + +Sometimes it is necessary to skip some notes. You can use @samp{ "" } and address@hidden \markup\null } in these cases. + address@hidden + address@hidden instructs lilypond to generate lyric extenders automatically. + address@hidden instructs lilypond not to generate lyric extenders +automatically. + address@hidden #num} sets the lower length limit for lyric extenders +to num staffspaces. No lyric extenders shorter than this will be automatically +generated. If currently inhibited, automatic generation of lyric extenders +is also enabled. + address@hidden #num} generates a lyric extender that starts num staffspaces left +from the associated note instead of a lyrics syllable. + address@hidden forces a lyric extenders where none would be generated otherwise. + address@hidden #num} forces a lyric extenders of length num staffspaces where +none would be generated otherwise. + address@hidden suppresses a lyric extender that would be automatically generated. + address@hidden #num} tells lilypond to stop the next lyric extender num +staffspaces left from the normal endpoint. + @seealso Internals Reference: @rinternals{LyricExtender}, @@ -1284,24 +1297,18 @@ More verses may be added in a similar way: \new Staff { \new Voice = "singleVoice" { \relative { - a'4 a a a - \repeat volta 3 { b4 b b b } + a'4 a a a + \repeat volta 3 { b4 b b b } c4 c c c - } + } } } \new Lyrics \lyricsto "singleVoice" { Not re -- peat -- ed. << { The first time words. } - \new Lyrics { - \set associatedVoice = "singleVoice" - Sec -- ond time words. - } - \new Lyrics { - \set associatedVoice = "singleVoice" - The third time words. - } + \new Lyrics { Sec -- ond time words. } + \new Lyrics { The third time words. } >> The end sec -- tion. } @@ -1324,26 +1331,22 @@ To position them correctly use @code{alignBelowContext}: \new Staff { \new Voice = "melody" { \relative { - a'4 a a a - \repeat volta 3 { b4 b b b } + a'4 a a a + \repeat volta 3 { b4 b b b } c4 c c c - } + } } } \new Lyrics = "firstVerse" \lyricsto "melody" { Not re -- peat -- ed. << { The first time words. } - \new Lyrics = "secondVerse" - \with { alignBelowContext = #"firstVerse" } { - \set associatedVoice = "melody" - Sec -- ond time words. - } - \new Lyrics = "thirdVerse" - \with { alignBelowContext = #"secondVerse" } { - \set associatedVoice = "melody" - The third time words. - } + \new Lyrics = "secondVerse" + \with { alignBelowContext = #"firstVerse" } + { Sec -- ond time words. } + \new Lyrics = "thirdVerse" + \with { alignBelowContext = #"secondVerse" } + { The third time words. } >> The end sec -- tion. } @@ -1396,25 +1399,18 @@ lyrics correctly. } @end lilypond address@hidden \skip @cindex skipping notes in lyrics @cindex lyrics, skipping notes But when the repeated section has different words, or when one of the @code{\alternative} blocks starts with a rest, a repeat -construct cannot be used around the words and @code{\skip} commands +construct cannot be used around the words and @samp{ "" } have to be inserted manually to skip over the notes in the alternative sections which do not apply. Note: do not use an underscore, @code{_}, to skip notes -- an underscore indicates a melisma, causing the preceding syllable -to be left-aligned. - address@hidden @address@hidden command must be followed by a number, -but this number is ignored in lyrics which derive their durations -from the notes in an associated melody through @code{\addlyrics} or address@hidden Each @address@hidden skips a single note of any -value, irrespective of the value of the following number.} +to be left-aligned and an extender to be generated. @lilypond[verbatim,quote,ragged-right] \score { @@ -1431,15 +1427,12 @@ value, irrespective of the value of the following number.} } \new Lyrics { \lyricsto "melody" { - The first time words. - \repeat unfold 2 { \skip 1 } - End here. + The first time words. "" "" End here. } } \new Lyrics { \lyricsto "melody" { - Sec -- ond - \repeat unfold 2 { \skip 1 } + Sec -- ond "" "" time words. } } @@ -1462,8 +1455,13 @@ The tie creates a melisma into the first alternative, but not into the second and subsequent alternatives, so to align the lyrics correctly it is necessary to disable the automatic creation of melismata over the volta section and insert manual skips. +Note the use of @code{\earlyExtender}. @lilypond[quote,verbatim] +\paper { + ragged-right = ##f +} + \score { << \new Staff { @@ -1480,10 +1478,10 @@ melismata over the volta section and insert manual skips. } \new Lyrics { \lyricsto "melody" { - \repeat volta 2 { Here's a __ } + \repeat volta 2 { Here's a } \alternative { - { \skip 1 verse } - { \skip 1 sec } + { _ verse } + { \earlyExtender #-4 sec -- } } ond one. } @@ -1500,40 +1498,15 @@ When the repeated section has different words a @code{\repeat} cannot be used around the lyrics and @code{\skip} commands need to be inserted manually, as before. address@hidden and @code{\earlyExtender} can be used together +with skips coded as @code{""} to give an optimal solution to the problem +of lyric extenders in such situations: + @lilypond[quote,verbatim] -\score { - << - \new Staff { - \time 2/4 - \new Voice = "melody" { - \relative { - \repeat volta 2 { b'4 b ~} - \alternative { { b b } { b \repeatTie c } } - c4 c - } - } - } - \new Lyrics { - \lyricsto "melody" { - Here's a __ verse. - \repeat unfold 2 { \skip 1 } - } - } - \new Lyrics { - \lyricsto "melody" { - Here's one - \repeat unfold 2 { \skip 1 } - more to sing. - } - } - >> +\paper { + ragged-right = ##f } address@hidden lilypond -If you wish to show extenders and hyphens into and out of -alternative sections these must be inserted manually. - address@hidden,verbatim] \score { << \new Staff { @@ -1548,15 +1521,12 @@ alternative sections these must be inserted manually. } \new Lyrics { \lyricsto "melody" { - Here's a __ verse. - \repeat unfold 2 { \skip 1 } + Here's a verse. "" "" } } \new Lyrics { \lyricsto "melody" { - Here's "a_" - \skip 1 - "_" sec -- ond one. + Here's \shortenExtender #4 one "" \earlyExtender #-4 more to sing. } } >> @@ -1667,7 +1637,7 @@ too short, since the lyrics are aligned only to the top voice: @lilypond[quote,verbatim] soprano = \relative { b'8( c d c) d2 } alto = \relative { g'2 b8( a g a) } -words = \lyricmode { la __ la __ } +words = \lyricmode { la la } \new Staff << \new Voice = "sopranoVoice" { \voiceOne \soprano } @@ -1686,7 +1656,7 @@ appropriately: soprano = \relative { b'8( c d c) d2 } alto = \relative { g'2 b8( a g a) } aligner = \relative { b'8( c d c) b( a g a) } -words = \lyricmode { la __ la __ } +words = \lyricmode { la la } \new Staff << \new Voice { \voiceOne \soprano } @@ -1703,7 +1673,7 @@ function, which does not allow lyrics on its own: soprano = \relative { b'8( c d c) d2 } alto = \relative { g'2 b8( a g a) } aligner = \relative { b'8( c d c) b( a g a) } -words = \lyricmode { la __ la __ } +words = \lyricmode { la la } \new Staff << \new Voice \partcombine \soprano \alto @@ -1728,7 +1698,7 @@ soprano = \relative { b'8( c d c) d2 } altoOne = \relative { g'2 b8( a b4) } altoTwo = \relative { d'2 g4( fis8 g) } aligner = \relative { b'8( c d c) d( d d d) } -words = \lyricmode { la __ la __ } +words = \lyricmode { la la } \new ChoirStaff \with {\accepts NullVoice } << \new Staff \soprano @@ -1944,7 +1914,7 @@ block: } \new Lyrics \with { includeGraceNotes = ##t } \lyricsto melody { - Ah __ fa + Ah fa } >> @end lilypond diff --git a/lily/extender-engraver.cc b/lily/extender-engraver.cc index 39fa7788de..c5b9587022 100644 --- a/lily/extender-engraver.cc +++ b/lily/extender-engraver.cc @@ -162,18 +162,12 @@ Extender_engraver::finalize () if (extender_) { completize_extender (extender_); - - if (!extender_->get_bound (RIGHT)) - extender_->warning (_ ("unterminated extender")); extender_ = 0; } if (pending_extender_) { completize_extender (pending_extender_); - - if (!pending_extender_->get_bound (RIGHT)) - pending_extender_->warning (_ ("unterminated extender")); pending_extender_ = 0; } } diff --git a/lily/lyric-extender.cc b/lily/lyric-extender.cc index 8afe2c5569..c1404b6961 100644 --- a/lily/lyric-extender.cc +++ b/lily/lyric-extender.cc @@ -45,51 +45,54 @@ Lyric_extender::print (SCM smob) common = common->common_refpoint (me->get_system (), X_AXIS); Real sl = me->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); + bool start_of_part_b = !left_edge->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")); + bool end_of_part_a = me->get_bound (RIGHT)->break_status_dir (); + bool force_extender = to_boolean (me->get_property ("force-extender")); + bool no_extender = to_boolean (me->get_property ("no-extender")); - extract_grob_set (me, "heads", heads); + if (!force_extender && no_extender) + return SCM_EOL; - if (!heads.size ()) + extract_grob_set (me, "heads", heads); + if (!heads.size () || (!force_extender && !start_of_part_b && !end_of_part_a && heads.size () < 2)) return SCM_EOL; common = common_refpoint_of_array (heads, common, X_AXIS); Real left_point = 0.0; - if (left_edge->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface"))) + if (!start_of_part_b) left_point = left_edge->extent (common, X_AXIS)[RIGHT]; - else if (heads.size ()) - left_point = heads[0]->extent (common, X_AXIS)[LEFT]; else - left_point = left_edge->extent (common, X_AXIS)[RIGHT]; + left_point = heads[0]->extent (common, X_AXIS)[LEFT]; if (isinf (left_point)) return SCM_EOL; - /* It seems that short extenders are even lengthened to go past the - note head, but haven't found a pattern in it yet. --hwn 1/1/04 */ - SCM minlen = me->get_property ("minimum-length"); - Real right_point - = left_point + (robust_scm2double (minlen, 0)); - - right_point = min (right_point, me->get_system ()->get_bound (RIGHT)->relative_coordinate (common, X_AXIS)); - - if (heads.size ()) - right_point = max (right_point, heads.back ()->extent (common, X_AXIS)[RIGHT]); - Real h = sl * robust_scm2double (me->get_property ("thickness"), 0); Drul_array