Contexts and engravers
Adding a figured bass above or below the notes
When writing a figured bass, you can place the figures above or below
the bass notes, by defining the
BassFigureAlignmentPositioning.direction property (exclusively
in a Staff context). Choices are #UP (or #1),
#CENTER (or #0) and #DOWN (or #-1).
This property can be changed as many times as you wish. Use
\once \override if you don’t want the override to apply to the
whole score.
bass={ \clefbass g4b,cd ed8cd2 } continuo=\figuremode{ <_>4<6>4<5/>4 \overrideStaff.BassFigureAlignmentPositioning.direction=#UP %\bassFigureStaffAlignmentUp <_+>4<6> \setStaff.useBassFigureExtenders=##t \overrideStaff.BassFigureAlignmentPositioning.direction=#DOWN %\bassFigureStaffAlignmentDown <4>4.<4>8<_+>4 } \score{ << \newStaff=bassStaff\bass \contextStaff=bassStaff\continuo >> }
Adding an extra staff
An extra staff can be added (possibly temporarily) after the start of a piece.
\score{ << \newStaff\relativec''{ c1|c|c|c|c } \newStaffGroup\relativec''{ \newStaff{ c1|c << { c1|d } \newStaff{ \once\omitStaff.TimeSignature c1|b } >> c1 } } >> }
Adding an extra staff at a line break
When adding a new staff at a line break, some extra space is
unfortunately added at the end of the line before the break (to fit in
a key signature change, which will never be printed anyway). The
workaround is to add a setting of
Staff.explicitKeySignatureVisibility as is shown in the example.
\score{ \newStaffGroup\relativec''{ \newStaff \keyf\major c1c^"Unwanted extra space"\break <<{c1|c} \newStaff{ \keyf\major \once\omitStaff.TimeSignature c1|c } >> c1|c^"Fixed here"\break <<{c1|c} \newStaff{ \once\setStaff.explicitKeySignatureVisibility=#end-of-line-invisible \keyf\major \once\omitStaff.TimeSignature c1|c } >> } }
Automatically changing the stem direction of the middle note based on the melody
LilyPond can alter the stem direction of the middle note on a staff so
that it follows the melody, by adding the Melody_engraver to the
Voice context.
The context property suspendMelodyDecisions may be used to turn
off this behavior locally.
\relativec''{ \time3/4 a8bgfbg| \setsuspendMelodyDecisions=##t abgfbg| \unsetsuspendMelodyDecisions cbdcbc| } \layout{ \context{ \Voice \consists"Melody_engraver" \autoBeamOff } }
Centered measure numbers
Scores of large ensemble works often have bar numbers placed beneath
the system, centered horizontally on the measure’s extent. This
snippet shows how the Measure_counter_engraver may be used to
simulate this notational practice. Here, the engraver has been added
to a Dynamics context.
This snippet presents a legacy method: starting from LilyPond 2.23.3,
\set Score.centerBarNumbers = ##t is enough.
\layout{ \context{ \Dynamics \consists#Measure_counter_engraver \overrideMeasureCounter.direction=#DOWN \overrideMeasureCounter.font-encoding=#'latin1 \overrideMeasureCounter.font-shape=#'italic % to control the distance of the Dynamics context from the staff: \overrideVerticalAxisGroup.nonstaff-relatedstaff-spacing.padding=#2 } \context{ \Score \remove"Bar_number_engraver" } } pattern=\repeatunfold7{c'4d'e'f'} \newStaffGroup<< \newStaff{ \pattern } \newStaff{ \pattern } \newDynamics{ \startMeasureCount s1*7 \stopMeasureCount } >>
Changing MIDI output to one channel per voice
When outputting MIDI, the default behavior is for each staff to represent one MIDI channel, with all the voices on a staff amalgamated. This minimizes the risk of running out of MIDI channels, since there are only 16 available per track.
However, by moving the Staff_performer to the Voice
context, each voice on a staff can have its own MIDI channel, as is
demonstrated by the following example: despite being on the same staff,
two MIDI channels are created, each with a different
midiInstrument.
\score{ \newStaff<< \newVoice\relativec'''{ \setmidiInstrument=#"flute" \voiceOne \keyg\major \time2/2 r2g-"Flute"~ gfis~ fis4g8fise2~ e4d8cisd2 } \newVoice\relativec''{ \setmidiInstrument=#"clarinet" \voiceTwo b1-"Clarinet" a2.b8a g2.fis8e fis2r } >> \layout{} \midi{ \context{ \Staff \remove"Staff_performer" } \context{ \Voice \consists"Staff_performer" } \tempo2=72 } }
Changing time signatures inside a polymetric section using \scaleDurations
The measureLength property, together with
measurePosition, determines when a bar line is needed. However,
when using \scaleDurations, the scaling of durations makes it
difficult to change time signatures. In this case,
measureLength should be set manually, using the
ly:make-moment callback. The second argument must be the same
as the second argument of \scaleDurations.
\layout{ \context{ \Score \remove"Timing_translator" } \context{ \Staff \consists"Timing_translator" } } << \newStaff{ \scaleDurations8/5{ \time6/8 \setTiming.measureLength=#(ly:make-moment6/5) b8bbbbb \time2/4 \setTiming.measureLength=#(ly:make-moment4/5) b4b } } \newStaff{ \clefbass \time2/4 c2def } >>
Chant or psalms notation
This form of notation is used for Psalm chant, where verses aren’t always the same length.
stemOff=\hideStaff.Stem stemOn=\undo\stemOff \score{ \newStaff\with{\remove"Time_signature_engraver"} { \keyg\minor \cadenzaOn \stemOffa'\brevebes'4g'4 \stemOna'2\section \stemOffa'\breveg'4a'4 \stemOnf'2\section \stemOffa'\breve^\markup{\italicflexe} \stemOng'2\fine } }
Creating blank staves
To create blank staves, generate empty measures then remove the
Bar_number_engraver from the Score context, and the
Time_signature_engraver, Clef_engraver and
Bar_engraver from the Staff context.
#(set-global-staff-size20) \score{ { \repeatunfold12{s1\break} } \layout{ indent=0\in \context{ \Staff \remove"Time_signature_engraver" \remove"Clef_engraver" \remove"Bar_engraver" } \context{ \Score \remove"Bar_number_engraver" } } } % uncomment these lines for "letter" size %{ \paper { #(set-paper-size "letter") ragged-last-bottom = ##f line-width = 7.5\in left-margin = 0.5\in bottom-margin = 0.25\in top-margin = 0.25\in } %} % uncomment these lines for "A4" size %{ \paper { #(set-paper-size "a4") ragged-last-bottom = ##f line-width = 180 left-margin = 15 bottom-margin = 10 top-margin = 10 } %}
Creating custom key signatures
LilyPond supports custom key signatures. In this example, print for D minor with an extended range of printed flats.
\newStaff\with{ \overrideStaffSymbol.line-count=#8 \overrideKeySignature.flat-positions=#'((-7.6)) \overrideKeyCancellation.flat-positions=#'((-7.6)) % presumably sharps are also printed in both octaves \overrideKeySignature.sharp-positions=#'((-6.7)) \overrideKeyCancellation.sharp-positions=#'((-6.7)) \overrideClef.stencil=# (lambda(grob)(grob-interpret-markupgrob #{\markup\combine \musicglyph"clefs.C" \translate#'(-3.-2) \musicglyph"clefs.F" #})) clefPosition=#3 middleCPosition=#3 middleCClefPosition=#3 } { \keyd\minor fbes,fbes, }
Cross staff stems
This snippet shows the use of the Span_stem_engraver and
\crossStaff to connect stems across staves automatically.
The stem length need not be specified, as the variable distance between noteheads and staves is calculated automatically.
\layout{ \context{ \PianoStaff \consists"Span_stem_engraver" } } { \newPianoStaff<< \newStaff{ <bd'>4rd'16\>e'8.g8r\! e'8f'g'4e'2 } \newStaff{ \clefbass \voiceOne \autoBeamOff \crossStaff{<eg>4e,g16a8.c8}d \autoBeamOn g8fg4c2 } >> }
Defining an engraver in Scheme: ambitus engraver
This example demonstrates how the ambitus engraver may be defined on
the user side, with a Scheme engraver. This is basically a rewrite in
Scheme of the code from lily/ambitus-engraver.cc.
#(use-modules(oopgoops)) %%% %%% Grob utilities %%% %%% These are literal rewrites of some C++ methods used by the ambitus engraver. #(define(ly:separation-item::add-conditional-itemgrobgrob-item) "Add @var{grob-item} to the array of conditional elements of @var{grob}. Rewrite of @code{Separation_item::add_conditional_item} from @file{lily/separation-item.cc}." (ly:pointer-group-interface::add-grobgrob'conditional-elementsgrob-item)) #(define(ly:accidental-placement::accidental-pitchaccidental-grob) "Get the pitch from the grob cause of @var{accidental-grob}. Rewrite of @code{accidental_pitch} from @file{lily/accidental-placement.cc}." (ly:event-property(ly:grob-property(ly:grob-parentaccidental-grobY)'cause) 'pitch)) #(define(ly:accidental-placement::add-accidentalgrobaccidental-grob) "Add @var{accidental-grob}, an @code{Accidental} grob, to the list of the accidental grobs of @var{grob}, an @code{AccidentalPlacement} grob. Rewrite of @code{Accidental_placement::add_accidental} from @file{lily/accidental-placement.cc}." (let((pitch(ly:accidental-placement::accidental-pitchaccidental-grob))) (set!(ly:grob-parentaccidental-grobX)grob) (let*((accidentals(ly:grob-objectgrob'accidental-grobs)) (handle(assq(ly:pitch-notenamepitch)accidentals)) (entry(ifhandle(cdrhandle)'()))) (set!(ly:grob-objectgrob'accidental-grobs) (assq-set!accidentals (ly:pitch-notenamepitch) (consaccidental-grobentry)))))) %%% %%% Ambitus data structure %%% %%% The <ambitus> class holds the various grobs that are created %%% to print an ambitus: %%% - ambitus-group: the grob that groups all the components of an ambitus %%% (Ambitus grob); %%% - ambitus-line: the vertical line between the upper and lower ambitus %%% notes (AmbitusLine grob); %%% - ambitus-up-note and ambitus-down-note: the note head and accidental %%% for the lower and upper note of the ambitus (see <ambitus-note> class %%% below). %%% The other slots define the key and clef context of the engraver: %%% - start-c0: position of middle c at the beginning of the piece. It %%% is used to place the ambitus notes according to their pitch; %%% - start-key-sig: the key signature at the beginning of the piece. It %%% is used to determine if accidentals shall be printed next to ambitus %%% notes. #(define-class<ambitus>() (ambitus-group#:accessorambitus-group) (ambitus-line#:accessorambitus-line) (ambitus-up-note#:getterambitus-up-note #:init-form(make<ambitus-note>)) (ambitus-down-note#:getterambitus-down-note #:init-form(make<ambitus-note>)) (start-c0#:accessorambitus-start-c0 #:init-value#f) (start-key-sig#:accessorambitus-start-key-sig #:init-value'())) %%% Accessor for the lower and upper note data of an ambitus #(define-method(ambitus-note(ambitus<ambitus>)direction) "If @var{direction} is @code{UP}, then return the upper ambitus note of @var{ambitus}, otherwise return the lower ambitus note." (if(=directionUP) (ambitus-up-noteambitus) (ambitus-down-noteambitus))) %%% The <ambitus-note> class holds the grobs that are specific to ambitus %%% (lower and upper) notes: %%% - head: an AmbitusNoteHead grob; %%% - accidental: an AmbitusAccidental grob, to be possibly printed next %%% to the ambitus note head. %%% Moreover: %%% - pitch is the absolute pitch of the note %%% - cause is the note event that causes this ambitus note, i.e. the lower %%% or upper note of the considered music sequence. #(define-class<ambitus-note>() (head#:accessorambitus-note-head #:init-value#f) (accidental#:accessorambitus-note-accidental #:init-value#f) (cause#:accessorambitus-note-cause #:init-value#f) (pitch#:accessorambitus-note-pitch #:init-value#f)) %%% %%% Ambitus engraving logics %%% %%% Rewrite of the code from @file{lily/ambitus-engraver.cc}. #(define(make-ambitustranslator) "Build an ambitus object: initialize all the grobs and their relations. The Ambitus grob contain all other grobs: Ambitus |- AmbitusLine |- AmbitusNoteHead for upper note |- AmbitusAccidental for upper note |- AmbitusNoteHead for lower note |- AmbitusAccidental for lower note The parent of an accidental is the corresponding note head, and the accidental is set as the 'accidental-grob of the note head so that is printed by the function that prints notes." ;; make the ambitus object (let((ambitus(make<ambitus>))) ;; build the Ambitus grob, which will contain all other grobs (set!(ambitus-groupambitus)(ly:engraver-make-grobtranslator'Ambitus'())) ;; build the AmbitusLine grob (line between lower and upper note) (set!(ambitus-lineambitus)(ly:engraver-make-grobtranslator'AmbitusLine'())) ;; build the upper and lower AmbitusNoteHead and AmbitusAccidental (for-each(lambda(direction) (let((head(ly:engraver-make-grobtranslator'AmbitusNoteHead'())) (accidental(ly:engraver-make-grobtranslator'AmbitusAccidental'())) (group(ambitus-groupambitus))) ;; The parent of the AmbitusAccidental grob is the ;; AmbitusNoteHead grob (set!(ly:grob-parentaccidentalY)head) ;; The AmbitusAccidental grob is set as the accidental-grob ;; object of the AmbitusNoteHead. This is later used by the ;; function that prints notes. (set!(ly:grob-objecthead'accidental-grob)accidental) ;; both the note head and the accidental grobs are added ;; to the main ambitus grob. (ly:axis-group-interface::add-elementgrouphead) (ly:axis-group-interface::add-elementgroupaccidental) ;; the note head and the accidental grobs are added to the ;; ambitus object (set!(ambitus-note-head(ambitus-noteambitusdirection)) head) (set!(ambitus-note-accidental(ambitus-noteambitusdirection)) accidental))) (listDOWNUP)) ;; The parent of the ambitus line is the lower ambitus note head (set!(ly:grob-parent(ambitus-lineambitus)X) (ambitus-note-head(ambitus-noteambitusDOWN))) ;; the ambitus line is added to the ambitus main grob (ly:axis-group-interface::add-element(ambitus-groupambitus)(ambitus-lineambitus)) ambitus)) #(define-method(initialize-ambitus-state(ambitus<ambitus>)translator) "Initialize the state of @var{ambitus}, by getting the starting position of middle C and key signature from @var{translator}'s context." (if(not(ambitus-start-c0ambitus)) (begin (set!(ambitus-start-c0ambitus) (ly:context-property(ly:translator-contexttranslator) 'middleCPosition 0)) (set!(ambitus-start-key-sigambitus) (ly:context-property(ly:translator-contexttranslator) 'keyAlterations))))) #(define-method(update-ambitus-notes(ambitus<ambitus>)note-grob) "Update the upper and lower ambitus pithes of @var{ambitus}, using @var{note-grob}." ;; Get the event that caused the note-grob creation ;; and check that it is a note-event. (let((note-event(ly:grob-propertynote-grob'cause))) (if(ly:in-event-class?note-event'note-event) ;; get the pitch from the note event (let((pitch(ly:event-propertynote-event'pitch))) ;; if this pitch is lower than the current ambitus lower ;; note pitch (or it has not been initialized yet), ;; then this pitch is the new ambitus lower pitch, ;; and conversely for upper pitch. (for-each(lambda(directionpitch-compare) (if(or(not(ambitus-note-pitch(ambitus-noteambitusdirection))) (pitch-comparepitch (ambitus-note-pitch(ambitus-noteambitusdirection)))) (begin (set!(ambitus-note-pitch(ambitus-noteambitusdirection)) pitch) (set!(ambitus-note-cause(ambitus-noteambitusdirection)) note-event)))) (listDOWNUP) (listly:pitch<?(lambda(p1p2) (ly:pitch<?p2p1)))))))) #(define-method(typeset-ambitus(ambitus<ambitus>)translator) "Typeset the ambitus: - place the lower and upper ambitus notes according to their pitch and the position of the middle C; - typeset or delete the note accidentals, according to the key signature. An accidental, if it is to be printed, is added to an AccidentalPlacement grob (a grob dedicated to the placement of accidentals near a chord); - both note heads are added to the ambitus line grob, so that a line should be printed between them." ;; check if there are lower and upper pitches (if(and(ambitus-note-pitch(ambitus-noteambitusUP)) (ambitus-note-pitch(ambitus-noteambitusDOWN))) ;; make an AccidentalPlacement grob, for placement of note accidentals (let((accidental-placement(ly:engraver-make-grob translator 'AccidentalPlacement (ambitus-note-accidental(ambitus-noteambitusDOWN))))) ;; For lower and upper ambitus notes: (for-each(lambda(direction) (let((pitch(ambitus-note-pitch(ambitus-noteambitusdirection)))) ;; set the cause and the staff position of the ambitus note ;; according to the associated pitch (set!(ly:grob-property(ambitus-note-head(ambitus-noteambitusdirection)) 'cause) (ambitus-note-cause(ambitus-noteambitusdirection))) (set!(ly:grob-property(ambitus-note-head(ambitus-noteambitusdirection)) 'staff-position) (+(ambitus-start-c0ambitus) (ly:pitch-stepspitch))) ;; determine if an accidental shall be printed for this note, ;; according to the key signature (let*((handle(or(assoc(cons(ly:pitch-octavepitch) (ly:pitch-notenamepitch)) (ambitus-start-key-sigambitus)) (assoc(ly:pitch-notenamepitch) (ambitus-start-key-sigambitus)))) (sig-alter(ifhandle(cdrhandle)0))) (cond((=(ly:pitch-alterationpitch)sig-alter) ;; the note alteration is in the key signature ;; => it does not have to be printed (ly:grob-suicide! (ambitus-note-accidental(ambitus-noteambitusdirection))) (set!(ly:grob-object(ambitus-note-head(ambitus-noteambitusdirection)) 'accidental-grob) '())) (else ;; otherwise, the accidental shall be printed (set!(ly:grob-property(ambitus-note-accidental (ambitus-noteambitusdirection)) 'alteration) (ly:pitch-alterationpitch))))) ;; add the AccidentalPlacement grob to the ;; conditional items of the AmbitusNoteHead (ly:separation-item::add-conditional-item (ambitus-note-head(ambitus-noteambitusdirection)) accidental-placement) ;; add the AmbitusAccidental to the list of the ;; AccidentalPlacement grob accidentals (ly:accidental-placement::add-accidental accidental-placement (ambitus-note-accidental(ambitus-noteambitusdirection))) ;; add the AmbitusNoteHead grob to the AmbitusLine grob (ly:pointer-group-interface::add-grob (ambitus-lineambitus) 'note-heads (ambitus-note-head(ambitus-noteambitusdirection))))) (listDOWNUP)) ;; add the AccidentalPlacement grob to the main Ambitus grob (ly:axis-group-interface::add-element(ambitus-groupambitus)accidental-placement)) ;; no notes ==> suicide the grobs (begin (for-each(lambda(direction) (ly:grob-suicide!(ambitus-note-accidental(ambitus-noteambitusdirection))) (ly:grob-suicide!(ambitus-note-head(ambitus-noteambitusdirection)))) (listDOWNUP)) (ly:grob-suicide!ambitus-line)))) %%% %%% Ambitus engraver definition %%% #(defineambitus-engraver (lambda(context) (let((ambitus#f)) ;; when music is processed: make the ambitus object, if not already built (make-engraver ((process-musictranslator) (if(notambitus) (set!ambitus(make-ambitustranslator)))) ;; set the ambitus clef and key signature state ((stop-translation-timesteptranslator) (ifambitus (initialize-ambitus-stateambitustranslator))) ;; when a note-head grob is built, update the ambitus notes (acknowledgers ((note-head-interfaceengravergrobsource-engraver) (ifambitus (update-ambitus-notesambitusgrob)))) ;; finally, typeset the ambitus according to its upper and lower notes ;; (if any). ((finalizetranslator) (ifambitus (typeset-ambitusambitustranslator))))))) %%% %%% Example %%% \score{ \newStaffGroup<< \newStaff{c'4des'e'fis'gis'} \newStaff{\clef"bass"c4des~deseesb,} >> \layout{\context{\Staff\consists#ambitus-engraver}} }
Displaying a whole GrandStaff system if only one of its staves is alive
In orchestral scores sometimes single or groups of instruments are
silent for a while and their staves can be removed for that time (with
\removeEmptyStaves).
When they play again it is often preferred to show the staves of
all instruments of such a group. This can be done adding the
Keep_alive_together_engraver in the grouper (e.g., a GrandStaff
or a StaffGroup).
In the example the violins are silent in the 2nd system and in the 3rd system. Only the first violin plays the last measure but the staff of the second violin is also displayed.
\score{ << \newStaffGroup="StaffGroup_woodwinds" << \newStaff="Staff_flute"\with{ instrumentName="Flute" shortInstrumentName="Fl" } \relativec'{ \repeatunfold3{c'4ccc|cccc|cccc|\break} } >> \newStaffGroup="StaffGroup_Strings" << \newGrandStaff="GrandStaff_violins" << \newStaff="StaffViolinI"\with{ instrumentName="Violin I" shortInstrumentName="Vi I" } \relativec''{ a1\repeatunfold7{s1}\repeatunfold12a16a4 } \newStaff="StaffViolinII"\with{ instrumentName="Violin II" shortInstrumentName="Vi II" } \relativec'{e1\repeatunfold8{s1}} >> \newStaff="Staff_cello"\with{ instrumentName="Cello" shortInstrumentName="Ce" } \relativec{\clefbass\repeatunfold9{c1}} >> >> } \layout{ indent=3.0\cm short-indent=1.5\cm \context{ \GrandStaff \consistsKeep_alive_together_engraver } \context{ \Staff \RemoveEmptyStaves } }
Engravers one-by-one
The notation problem, creating a certain symbol, is handled by plugins. Each plugin is called an Engraver. In this example, engravers are switched on one by one, in the following order:
- note heads,
- staff symbol,
- clef,
- stem,
- beams, slurs, accents,
- accidentals, bar lines, time signature and key signature.
Engravers are grouped. For example, note heads, slurs, beams etc. form
a Voice context. Engravers for key signature, accidentals, bar
line, etc. form a Staff context.
%% sample music topVoice=\relativec'{ \keyd\major es8([g]a[fis]) b4 b16[-.b-.b-.cis-.] d4-> } botVoice=\relativec'{ \keyd\major c8[(f]b[a)] es4 es16[-.es-.es-.fis-.] b4-> } hoom=\relativec{ \keyd\major \clefbass g8-.r r4 fis8-. r8 r4 b'4-> } pah=\relativec'{ r8b-. r4 r8g8-. r16g-.r8 \cleftreble fis'4-> } % % setup for Request->Element conversion. Guru-only % MyStaff=\context{ \type"Engraver_group" \nameStaff \description"Handles clefs, bar lines, keys, accidentals. It can contain @code{Voice} contexts." \consists"Output_property_engraver" \consists"Font_size_engraver" \consists"Volta_engraver" \consists"Separating_line_group_engraver" \consists"Dot_column_engraver" \consists"Ottava_spanner_engraver" \consists"Rest_collision_engraver" \consists"Piano_pedal_engraver" \consists"Piano_pedal_align_engraver" \consists"Instrument_name_engraver" \consists"Grob_pq_engraver" \consists"Forbid_line_break_engraver" \consists"Axis_group_engraver" \consists"Pitch_squash_engraver" localAlterations=#'() % explicitly set instrumentName, so we don't get % weird effects when doing instrument names for % piano staves instrumentName=#'() shortInstrumentName=#'() \accepts"Voice" \defaultchild"Voice" } MyVoice=\context{ \type"Engraver_group" \nameVoice \description" Corresponds to a voice on a staff. This context handles the conversion of dynamic signs, stems, beams, super- and subscripts, slurs, ties, and rests. You have to instantiate this explicitly if you want to have multiple voices on the same staff." localAlterations=#'() \consists"Font_size_engraver" % must come before all \consists"Output_property_engraver" \consists"Arpeggio_engraver" \consists"Multi_measure_rest_engraver" \consists"Text_spanner_engraver" \consists"Grob_pq_engraver" \consists"Note_head_line_engraver" \consists"Glissando_engraver" \consists"Ligature_bracket_engraver" \consists"Breathing_sign_engraver" % \consists "Rest_engraver" \consists"Grace_beam_engraver" \consists"New_fingering_engraver" \consists"Chord_tremolo_engraver" \consists"Percent_repeat_engraver" \consists"Slash_repeat_engraver" %{ Must come before text_engraver, but after note_column engraver. %} \consists"Text_engraver" \consists"Dynamic_engraver" \consists"Dynamic_align_engraver" \consists"Fingering_engraver" \consists"Script_column_engraver" \consists"Rhythmic_column_engraver" \consists"Cluster_spanner_engraver" \consists"Tie_engraver" \consists"Tie_engraver" \consists"Tuplet_engraver" \consists"Note_heads_engraver" \consists"Rest_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyStaff=\context{ \MyStaff \consists"Staff_symbol_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyStaff=\context{ \MyStaff \consists"Clef_engraver" \remove"Pitch_squash_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyVoice=\context{ \MyVoice \consists"Stem_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyVoice=\context{ \MyVoice \consists"Beam_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyVoice=\context{ \MyVoice \consists"Phrasing_slur_engraver" \consists"Slur_engraver" \consists"Script_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyStaff=\context{ \MyStaff \consists"Bar_engraver" \consists"Time_signature_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } } MyStaff=\context{ \MyStaff \consists"Accidental_engraver" \consists"Key_engraver" } \score{ \topVoice \layout{ \context{\MyStaff} \context{\MyVoice} } }
Mensurstriche layout (bar lines between the staves)
Mensurstriche, bar lines between but not through staves, can be
printed by setting measureBarType to "-span|" and
using a grouping context that allows span bars, such as
StaffGroup.
\layout{ \context{ \Staff measureBarType="-span|" } } music=\fixedc''{ c1 d2\sectione2 f1\fine } \newStaffGroup<< \newStaff\music \newStaff\music >>
Nesting staves
The property systemStartDelimiterHierarchy can be used to make
more complex nested staff groups. The command
\set StaffGroup.systemStartDelimiterHierarchy takes an
alphabetical list of the number of staves produced. Before each staff a
system start delimiter can be given. It has to be enclosed in brackets
and takes as much staves as the brackets enclose. Elements in the list
can be omitted, but the first bracket takes always the complete number
of staves. The possibilities are SystemStartBar,
SystemStartBracket, SystemStartBrace, and
SystemStartSquare.
\newStaffGroup \relativec''<< \overrideStaffGroup.SystemStartSquare.collapse-height=#4 \setStaffGroup.systemStartDelimiterHierarchy =#'(SystemStartSquare(SystemStartBrace(SystemStartBracketa (SystemStartSquareb))c)d) \newStaff{c1} \newStaff{c1} \newStaff{c1} \newStaff{c1} \newStaff{c1} >>
Numbering groups of measures
This snippet demonstrates the use of the
Measure_counter_engraver to number groups of successive
measures. Any stretch of measures may be numbered, whether consisting
of repetitions or not.
The engraver must be added to the appropriate context. Here, a
Staff context is used; another possibility is a Dynamics
context.
The counter is begun with \startMeasureCount and ended with
\stopMeasureCount. Numbering will start by default with
1, but this behavior may be modified by overriding the
count-from property.
When a measure extends across a line break, the number will appear twice, the second time in parentheses.
\layout{ \context{ \Staff \consists#Measure_counter_engraver } } \newStaff{ \startMeasureCount \repeatunfold7{ c'4d'e'f' } \stopMeasureCount \bar"||" g'4f'e'd' \overrideStaff.MeasureCounter.count-from=#2 \startMeasureCount \repeatunfold5{ g'4f'e'd' } g'4f' \bar"" \break e'4d' \repeatunfold7{ g'4f'e'd' } \stopMeasureCount }
Print ChordNames with same root and different bass as slash and bass-note
To print subsequent ChordNames only differing in its bass note
as slash and bass note use the here defined engraver. The behaviour may
be controlled in detail by the chordChanges context property.
#(defineBass_changes_equal_root_engraver (lambda(ctx) "For sequential @code{ChordNames} with same root, but different bass, the root markup is dropped: D D/C D/B -> D /C /B The behaviour may be controlled by setting the @code{chordChanges} context-property." (let((chord-pitches'()) (last-chord-pitches'()) (bass-pitch#f)) (make-engraver ((initializethis-engraver) (let((chord-note-namer(ly:context-propertyctx'chordNoteNamer))) ;; Set 'chordNoteNamer, respect user setting if already done (ly:context-set-property!ctx'chordNoteNamer (if(procedure?chord-note-namer) chord-note-namer note-name->markup)))) (listeners ((note-eventthis-engraverevent) (let*((pitch(ly:event-propertyevent'pitch)) (pitch-name(ly:pitch-notenamepitch)) (pitch-alt(ly:pitch-alterationpitch)) (bass(ly:event-propertyevent'bass#f)) (inversion(ly:event-propertyevent'inversion#f))) ;; Collect notes of the chord ;; - to compare inversed chords we need to collect the bass note ;; as usual member of the chord, whereas an added bass must be ;; treated separate from the usual chord-notes ;; - notes are stored as pairs containing their ;; pitch-name (an integer), i.e. disregarding their octave and ;; their alteration (cond(bass(set!bass-pitchpitch)) (inversion (set!bass-pitchpitch) (set!chord-pitches (cons(conspitch-namepitch-alt)chord-pitches))) (else (set!chord-pitches (cons(conspitch-namepitch-alt)chord-pitches))))))) (acknowledgers ((chord-name-interfacethis-engravergrobsource-engraver) (let((chord-changes(ly:context-propertyctx'chordChanges#f))) ;; If subsequent chords are equal apart from their bass, ;; reset the 'text-property. ;; Equality is done by comparing the sorted lists of this chord's ;; elements and the previous chord. Sorting is needed because ;; inverted chords may have a different order of pitches. ;; `chord-changes' needs to be true (if(andbass-pitch chord-changes (equal? (sortchord-pitchescar<) (sortlast-chord-pitchescar<))) (ly:grob-set-property!grob'text (make-line-markup (list (ly:context-propertyctx'slashChordSeparator) ((ly:context-propertyctx'chordNoteNamer) bass-pitch (ly:context-propertyctx'chordNameLowercaseMinor)))))) (set!last-chord-pitcheschord-pitches) (set!chord-pitches'()) (set!bass-pitch#f)))) ((finalizethis-engraver) (set!last-chord-pitches'())))))) myChords=\chordmode{ %\germanChords \setchordChanges=##t d2:md:m/cis d:m/c \setchordChanges=##f d:m/b e1:7 \setchordChanges=##t e \break \once\setchordChanges=##f e1/f e2/gise/+gisee:m/fd:md:m/cisd:m/c \setchordChanges=##f d:m/b } << \newChordNames \with{\consists#Bass_changes_equal_root_engraver} \myChords \newStaff\myChords >>
Removing bar numbers from a score
Bar numbers can be removed entirely by removing the
Bar_number_engraver from the Score context.
\layout{ \context{ \Score \omitBarNumber % or: %\remove "Bar_number_engraver" } } \relativec''{ c4ccc\break c4ccc }
Use square bracket at the start of a staff group
The system start delimiter SystemStartSquare can be used by
setting it explicitly in a StaffGroup or ChoirStaff
context.
\score{ \newStaffGroup{<< \setStaffGroup.systemStartDelimiter=#'SystemStartSquare \newStaff{c'4d'e'f'} \newStaff{c'4d'e'f'} >>} }
Using marklines in a Frenched score
Using MarkLine contexts (such as in
LSR1010) in a Frenched
score can be problematic if all the staves between two MarkLines
are removed in one system. The Keep_alive_together_engraver can
be used within each StaffGroup to keep the MarkLine alive
only as long as the other staves in the group stay alive.
bars={ \tempo"Allegro"4=120 s1*2 \repeatunfold5{\mark\defaults1*2} \bar"||" \tempo"Adagio"4=40 s1*2 \repeatunfold8{\mark\defaults1*2} \bar"|." } winds=\repeatunfold120{c''4} trumpet={\repeatunfold8g'2R1*16\repeatunfold4g'2R1*8} trombone={\repeatunfold4c'1R1*8d'1R1*17} strings=\repeatunfold240{c''8} #(set-global-staff-size16) \paper{ systems-per-page=5 ragged-last-bottom=##f } \layout{ indent=15\mm short-indent=5\mm \context{ \nameMarkLine \typeEngraver_group \consistsOutput_property_engraver \consistsAxis_group_engraver \consistsMark_engraver \consistsMetronome_mark_engraver \consistsStaff_collecting_engraver \overrideVerticalAxisGroup.remove-empty=##t \overrideVerticalAxisGroup.remove-layer=#'any \overrideVerticalAxisGroup.staff-affinity=#DOWN \overrideVerticalAxisGroup.nonstaff-relatedstaff-spacing.padding=1 keepAliveInterfaces=#'() } \context{ \Staff \overrideVerticalAxisGroup.remove-empty=##t \overrideVerticalAxisGroup.remove-layer=##f } \context{ \StaffGroup \acceptsMarkLine \consistsKeep_alive_together_engraver } \context{ \Score \removeMark_engraver \removeMetronome_mark_engraver \removeStaff_collecting_engraver } } \score{ << \newStaffGroup="winds"\with{ instrumentName="Winds" shortInstrumentName="Winds" }<< \newMarkLine\bars \newStaff\winds >> \newStaffGroup="brass"<< \newMarkLine\bars \newStaff="trumpet"\with{ instrumentName="Trumpet" shortInstrumentName="Tpt" }\trumpet \newStaff="trombone"\with{ instrumentName="Trombone" shortInstrumentName="Tbn" }\trombone >> \newStaffGroup="strings"\with{ instrumentName="Strings" shortInstrumentName="Strings" }<< \newMarkLine\bars \newStaff="strings"{\strings} >> >> }
Vocal ensemble template with lyrics aligned below and above the staves
This template is basically the same as the simple “Vocal ensemble”
template, with the exception that here all the lyrics lines are placed
using alignAboveContext and alignBelowContext.
global={ \keyc\major \time4/4 } sopMusic=\relativec''{ c4cc8[(b)]c4 } sopWords=\lyricmode{ hihihihi } altoMusic=\relativec'{ e4fde } altoWords=\lyricmode{ hahahaha } tenorMusic=\relativec'{ g4afg } tenorWords=\lyricmode{ huhuhuhu } bassMusic=\relativec{ c4cgc } bassWords=\lyricmode{ hohohoho } \score{ \newChoirStaff<< \newStaff="women"<< \newVoice="sopranos"{\voiceOne<<\global\sopMusic>>} \newVoice="altos"{\voiceTwo<<\global\altoMusic>>} >> \newLyrics\with{alignAboveContext=#"women"} \lyricsto"sopranos"\sopWords \newLyrics\with{alignBelowContext=#"women"} \lyricsto"altos"\altoWords % we could remove the line about this with the line below, since % we want the alto lyrics to be below the alto Voice anyway. % \new Lyrics \lyricsto "altos" \altoWords \newStaff="men"<< \clefbass \newVoice="tenors"{\voiceOne<<\global\tenorMusic>>} \newVoice="basses"{\voiceTwo<<\global\bassMusic>>} >> \newLyrics\with{alignAboveContext=#"men"} \lyricsto"tenors"\tenorWords \newLyrics\with{alignBelowContext=#"men"} \lyricsto"basses"\bassWords % again, we could replace the line above this with the line below. % \new Lyrics \lyricsto "basses" \bassWords >> }
Vocal ensemble template with verse and refrain
This template creates a score which starts with a solo verse and
continues into a refrain for two voices. It also demonstrates the use
of spacer rests within the \global variable to define meter
changes (and other elements common to all parts) throughout the entire
score.
global={ \keyg\major % verse \time3/4 s2.*2 \break % refrain \time2/4 s2*2 \bar"|." } SoloNotes=\relativeg'{ \clef"treble" % verse g4gg| b4bb| % refrain R2*2| } SoloLyrics=\lyricmode{ Onetwothree| fourfivesix| } SopranoNotes=\relativec''{ \clef"treble" % verse R2.*2| % refrain c4c| g4g| } SopranoLyrics=\lyricmode{ lala| lala| } BassNotes=\relativec{ \clef"bass" % verse R2.*2| % refrain c4e| d4d| } BassLyrics=\lyricmode{ dumdum| dumdum| } \score{ << \newVoice="SoloVoice"<<\global\SoloNotes>> \newLyrics\lyricsto"SoloVoice"\SoloLyrics \newChoirStaff<< \newVoice="SopranoVoice"<<\global\SopranoNotes>> \newLyrics\lyricsto"SopranoVoice"\SopranoLyrics \newVoice="BassVoice"<<\global\BassNotes>> \newLyrics\lyricsto"BassVoice"\BassLyrics >> >> \layout{ ragged-right=##t \context{\Staff % these lines prevent empty staves from being printed \RemoveEmptyStaves \overrideVerticalAxisGroup.remove-first=##t } } }