Contexts and engravers

Changing defaults

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
>>
}

[image of music]


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
}
}
>>
}

[image of music]


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
}
>>
}
}

[image of music]


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
}
}

[image of music]


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
}
>>

[image of music]


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
}
}

[image of music]


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
}
>>

[image of music]


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
}
}

[image of music]


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
}
%}

[image of music]


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,
}

[image of music]


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
}
>>
}

[image of music]


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}}
}

[image of music]


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
}
}

[image of music]


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}
}
}

[image of music]


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
>>

[image of 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}
>>

[image of music]


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
}

[image of music]


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
>>

[image of music]


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
}

[image of music]


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'}
>>}
}

[image of music]


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}
>>
>>
}

[image of music]


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
>>
}

[image of music]


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
}
}
}

[image of music]


<< Back to Documentation Index

LilyPond — Snippets v2.24.4 (stable-branch).

AltStyle によって変換されたページ (->オリジナル) /