F clef on 5th line
@item percussion
percussion clef
+@item tab
+ tablature clef
@end table
By adding @code{_8} or @code{^8} to the clef name, the clef is
This section describes how to change the way that accidentals are
inserted automatically before the running notes.
-
-@menu
-* Using the predefined accidental variables::
-* Customized accidental rules::
-@end menu
-
-@node Using the predefined accidental variables
-@subsection Using the predefined accidental variables
-
-
-Common rules for typesetting macros have been canned in a
+Common rules for typesetting accidentals have been canned in a
function. This function is called as follows:
@cindex @code{set-accidental-style}
@end lilypond
@end table
-@node Customized accidental rules
-@subsection Customized accidental rules
-
-For determining when to print an accidental, several different rules
-are tried. The rule that gives the highest number of accidentals is
-used. Each rule consists of
-@table @var
-@item context:
- In which context is the rule applied. For example, if
-@var{context} is @internalsref{Score} then all staves share
-accidentals, and if @var{context} is @internalsref{Staff} then all
-voices in the same staff share accidentals, but staves do not.
-
-@item octavation:
- Whether the accidental changes all octaves or only the current
- octave. Valid choices are
-
- @table @samp
- @item same-octave:
- This is the default algorithm. Accidentals are typeset if the note changes
- the accidental of that note in that octave. Accidentals lasts to the end of the measure
- and then as many measures as specified in the value. I.e. 1 means to the end
- of next measure, -1 means to the end of previous measure (that is: no duration at all), etc. #t means forever.
- @item any-octave:
- Accidentals are typeset if the note is different from
- the previous note on the same pitch in any octave. The value has same meaning as in
- same-octave.
- @end table
-
-@item laziness
-
- Over how many bar lines the accidental lasts.
- If @var{laziness} is @code{-1} then the accidental is forget
- immediately, and if @var{laziness} is @code{#t} then the accidental
- lasts forever.
-@end table
-
@seealso
@refbugs
- Simultaneous notes are considered to be entered in
-sequential mode. This means that in a chord the accidentals are
-typeset as if the notes in the chord happened once at a time - in the
-order in which they appear in the input file.
-
-This is only a problem when there are simultaneous notes whose
-accidentals depend on each other. The problem only occurs when using
-non-default accidentals. In the default scheme, accidentals only
-depend on other accidentals with the same pitch on the same staff, so
-no conflicts possible.
-
-This example shows two examples of the same music giving different
-accidentals depending on the order in which the notes occur in the
-input file:
+Simultaneous notes are considered to be entered in sequential
+mode. This means that in a chord the accidentals are typeset as if the
+notes in the chord happened once at a time - in the order in which
+they appear in the input file.
-@lilypond[raggedright,fragment,verbatim]
-\set Staff.autoAccidentals = #'( Staff (any-octave . 0) )
-cis'4 <c'' c'> r2 | cis'4 <c' c''> r2
-| <cis' c''> r | <c'' cis'> r |
-@end lilypond
+This is only a problem when accidentals in a chord depend on each
+other. This problem can be solved by manually inserting @code{!} and
+@code{?} for the problematic notes.
-This problem can be solved by manually inserting @code{!} and @code{?}
-for the problematic notes.
+In the default scheme, accidentals only depend on other
+accidentals with the same pitch on the same staff, so no conflicts are
+possible.
@node Expressive marks
@section Expressive marks
If the layout of grace sections must be changed throughout the music,
then this can be accomplished through the function
-@code{add-grace-property}. The following example
-undefines the Stem direction grace section, so stems do not always
-point up.
+@code{add-grace-property}. The following example undefines the Stem
+direction for this grace, so stems do not always point up.
@example
\new Staff @{
Program reference: @internalsref{Glissando}, and @internalsref{GlissandoEvent}.
+Example files: @file{input/regression,glissando.ly}
+
+
@refbugs
-Adding additional texts (such as @emph{gliss.}) is not supported.
+Printing text over the line (such as @emph{gliss.}) is not supported.
@node Dynamics
c2\sf c\rfz
@end lilypond
-@cindex @code{\cr}
-@cindex @code{\rc}
-@cindex @code{\decr}
-@cindex @code{\rced}
@cindex @code{\<}
@cindex @code{\>}
@cindex @code{\"!}
use spacer notes if multiple marks during one note are needed:
@lilypond[fragment,verbatim]
- c''\< c''\! d''\decr e''\rced
+ c''\< c''\! d''\> e''\!
<< f''1 { s4 s4\< s4\! \> s4\! } >>
@end lilypond
This may give rise to very short hairpins. Use @code{minimum-length}
example:
@example
- \override Staff.Hairpin #'minimum-length = #5
+ \override Staff.Hairpin #'minimum-length = #5
@end example
You can also use a text saying @emph{cresc.} instead of hairpins. Here
is an example how to do it:
@lilypond[fragment,relative=2,verbatim]
- c4 \cresc c4 c c c \endcresc c4
+ \setTextCresc
+ c \< d e f\!
+ \setHairpinCresc
+ e\> d c b\!
@end lilypond
@cindex crescendo
@seealso
-Program reference: @internalsref{CrescendoEvent}, @internalsref{DecrescendoEvent}, and
+Program reference: @internalsref{CrescendoEvent},
+@internalsref{DecrescendoEvent}, and
@internalsref{AbsoluteDynamicEvent}.
-Dynamics are objects of @internalsref{DynamicText} and
-@internalsref{Hairpin}. Vertical positioning of these symbols is
-handled by the @internalsref{DynamicLineSpanner} object.
-
-If you want to adjust padding or vertical direction of the dynamics, you
-must set properties for the @internalsref{DynamicLineSpanner} object.
+Dynamics @internalsref{DynamicText} and @internalsref{Hairpin}
+objects. Vertical positioning of these symbols is handled by the
+@internalsref{DynamicLineSpanner} object.
@node Repeats
@cindex expanding repeats
-For instructions on how to unfold repeats for MIDI output, see the
+For instructions on how to expand repeats for MIDI output, see the
example file @inputfileref{input/test,unfold-all-repeats.ly}.
Tremolo marks can also be put on a single note. In this case, the
note should not be surrounded by braces.
@lilypond[verbatim,raggedright]
- \repeat "tremolo" 4 c16
+ \repeat "tremolo" 4 c'16
@end lilypond
A similar mechanism is the tremolo subdivision, described in
@refbugs
-Tremolos in this style do not carry over into the MIDI output.
+Tremolos entered in this way do not carry over into the MIDI output.
@seealso
similar to @code{notes}. Each piece of percussion has a full name and
an abbreviated name, and both be used in input files:
+@example
+ hihat hh bassdrum bd
+@end example
@lilypond[raggedright]
- \drums { hihat4 hh4 }
+ \new DrumStaff \drums { hihat hh bassdrum bd
+ }
@end lilypond
The complete list of drum names is in the init file
polyphonic notation, described in @ref{Polyphony}, can also be used if
the @internalsref{DrumVoices} are instantiated by hand first. For example,
-@lilypond[fragment]
+@lilypond[fragment,verbatim]
\drums \new DrumStaff <<
\context DrumVoice = "1" { s1 *2 }
\context DrumVoice = "2" { s1 *2 }
%% need to do this, because of indented @itemize
linewidth= 9 \cm
\context { \ScoreContext
+ \override LyricText #'font-family = #'typewriter
\override BarNumber #'transparent =##T
}}}
@end lilypond
minimumVerticalExtent = #'(-3.0 . 4.0)
drumStyleTable = #timbales-style
} \mus
- \context Lyrics \nam
+ \context Lyrics {
+ \override LyricText #'font-family = #'typewriter
+
+ \nam }
>>
}
@end lilypond
\override Stem #'transparent = ##t
\override Stem #'Y-extent-callback = ##f
} \mus
- \context Lyrics \nam
+ \context Lyrics {
+ \override LyricText #'font-family = #'typewriter
+\nam }
>>
}
@end lilypond
\override Stem #'transparent = ##t
\override Stem #'Y-extent-callback = ##f
} \mus
- \context Lyrics \nam
+ \context Lyrics {
+ \override LyricText #'font-family = #'typewriter
+\nam }
>>
}
@end lilypond
\override Stem #'transparent = ##t
\override Stem #'Y-extent-callback = ##f
} \mus
- \context Lyrics \nam
+ \context Lyrics {
+ \nam
+ \override LyricText #'font-family = #'typewriter
+}
>>
}
@end lilypond
@refbugs
-Short polyphonic notation, @code{<< @dots{} \\ @dots{} >>}, does not
-work for @internalsref{DrumVoices}.
-
Because general MIDI does not contain rim shots, the sidestick is used
for this purpose instead.
What is printed can be modified by setting @code{pedal@var{X}Strings},
where @var{X} is one of the pedal types: @code{Sustain},
-@code{Sostenuto} or @code{UnaCorda}. Refer to the generated
-documentation of @internalsref{SustainPedal} for more information.
+@code{Sostenuto} or @code{UnaCorda}. Refer to
+@internalsref{SustainPedal} in the program reference for more
+information.
Pedals can also be indicated by a sequence of brackets, by setting the
@code{pedalSustainStyle} property to @code{bracket} objects:
>>
@end lilypond
+@seealso
+
The associated object is @internalsref{VoiceFollower}.
@refcommands
the resulting string. As a consequence, spaces must be inserted around
property commands:
@example
- \override Score . LyricText #'font-shape = #'italic
+ \override Score . LyricText #'font-shape = #'italic
@end example
@cindex @code{_}
@end example
@cindex hyphens
-Hyphens can be entered as ordinary hyphens at the end of a syllable, i.e.
-@example
- soft- ware
-@end example
-These will be attached to the end of the first syllable.
-
-Centered hyphens are entered using the special `@code{-}@code{-}' lyric
-as a separate word between syllables. The hyphen will have variable
-length depending on the space between the syllables and it will be
-centered between the syllables.
+Centered hyphens are entered as `@code{-}@code{-}' between syllables.
+The hyphen will have variable length depending on the space between
+the syllables and it will be centered between the syllables.
@cindex melisma
@cindex extender
@seealso
-Program reference: @internalsref{LyricEvent}, @internalsref{HyphenEvent}, and
-@internalsref{ExtenderEvent}.
+Program reference: events @internalsref{LyricEvent},
+@internalsref{HyphenEvent}, and @internalsref{ExtenderEvent}. Objects:
+@internalsref{LyricHyphen}, @internalsref{LyricExtender} and
+@internalsref{LyricText}.
Examples: @inputfileref{input/test,lyric-hyphen-retain.ly}.
@end example
and then combine the appropriate melodies and lyric lines:
@example
- \lyricsto "soprano" \new Lyrics @emph{the lyrics}
+ \lyricsto "soprano" \context Lyrics = sopranoLyrics
+ @emph{the lyrics}
@end example
@noindent
In addition, notes are considered a melisma if they are manually
beamed, and automatic beaming (see @ref{Setting automatic beam
-behavior}) is switched off. The criteria for deciding melismata
-can be tuned with the property @code{melismaBusyProperties}. See
-@internalsref{Melisma_translator} for more information.
+behavior}) is switched off. The criteria for deciding melismata can
+be tuned with the property @code{melismaBusyProperties}. See
+@internalsref{Melisma_translator} in the program reference for more
+information.
When multiple stanzas are put on the same melody, it can happen that
two stanzas have melismata in different locations. This can be
<< \notes \relative c'' \context Voice = duet { \time 3/4
g2 e4 a2 f4 g2. }
\lyrics << \lyricsto "duet" \new Lyrics {
- \set stanza = "B."
\set vocNam = "Bert"
Hi, my name is bert. }
\lyricsto "duet" \new Lyrics {
- \set stanza = "E."
\set vocNam = "Ernie"
Ooooo, ch\'e -- ri, je t'aime.
}
Stanza numbers can be added by setting @code{stanza}, e.g.
-@example
- \set stanza = "B."
- @dots{}
- \set stanza = "E."
-@end example
-
-Notice how dots are surrounded with spaces in @code{\lyrics} mode, to
-prevent @code{stanza} being interpreted as a single
-string.
+@lilypond
+<< \context Voice = duet { \time 3/4
+ g2 e4 a2 f4 g2. }
+ \lyrics \lyricsto "duet" \new Lyrics {
+ \set vocNam = "1. "
+ Hi, my name is bert.
+ }
+>>
+@end lilypond
This example also demonstrates how names of the singers can be added
using @code{vocalName} analogous to instrument annotations for staves.
@subsection Ambitus
@cindex ambitus
-The term @emph{ambitus} (plural: ambituses) denotes a range of pitches
-for a given voice in a part of music. It also may denote the pitch
-range that a musical instrument is capable of playing. Most musical
-instruments have their ambitus standardized (or at least there is
-agreement upon the minimal ambitus of a particular type of
-instrument), such that a composer or arranger of a piece of music can
-easily meet the ambitus constraints of the targeted instrument.
-However, the ambitus of the human voice depends on individual
-physiological state, including education and training of the voice.
-Therefore, a singer potentially has to check for each piece of music
-if the ambitus of that piece meets his individual capabilities. This
-is why the ambitus of a piece may be of particular value to vocal
-performers.
-
-The ambitus is typically notated on a per-voice basis at the very
-beginning of a piece, e.g. nearby the initial clef or time signature of
-each staff. The range is graphically specified by two note heads, that
-represent the minimum and maximum pitch. Some publishers use a textual
-notation: they put the range in words in front of the corresponding
-staff. LilyPond only supports the graphical ambitus notation.
-
-To apply, add the @internalsref{Ambitus_engraver} to the
-@internalsref{Voice} context, i.e.
+The term @emph{ambitus} denotes a range of pitches for a given voice
+in a part of music. It also may denote the pitch range that a musical
+instrument is capable of playing. Ambituses are printed on vocal
+parts, so singers can easily determine if it meets his or her
+capabilities.
+
+It denoted at the beginning of a piece near the initial clef. The
+range is graphically specified by two note heads, that represent the
+minimum and maximum pitch. To print such ambituses, add the
+@internalsref{Ambitus_engraver} to the @internalsref{Voice} context,
+for example,
@example
\paper @{
This results in the following output:
@lilypond[raggedright]
-upper = \notes \relative c {
- \clef "treble"
- \key c \minor
- as'' c e2 bes f cis d4 e f2 g
-}
-lower = \notes \relative c {
- \clef "treble"
- \key e \major
- e'4 b g a c es fis a cis b a g f e d2
-}
\score {
- \context ChoirStaff {
- <<
- \new Staff { \upper }
- \new Staff { \lower }
- >>
- }
+ \context ChoirStaff
+ \notes \relative c'' <<
+ \new staff {
+ as'' c e2 cis,2
+ }
+ \new Staff {
+ es4 b c f as g
+ }
+ >>
\paper {
\context {
\StaffContext
@example
-e8 fis gis a b cis' dis' e'
+e16 fis gis a b4
\set TabStaff.minimumFret = #8
-e8 fis gis a b cis' dis' e'
+e16 fis gis a b4
@end example
-@lilypond[noindent]
+@lilypond[noindent,raggedright]
frag = \notes {
\key e \major
- e8 fis gis a b cis' dis' e'
+ e16 fis gis a b4
\set TabStaff.minimumFret = #8
- e8 fis gis a b cis' dis' e'
+ e16 fis gis a b4
}
\score {
\context StaffGroup <<
>>
@end lilypond
-It is possible to change the Scheme function to format the tablature
-note text. The default is @code{fret-number-tablature-format}, which
-uses the fret number. For instruments that do not use this notation,
-you can create a special tablature formatting function. This function
-takes three argument: string number, string tuning and note pitch.
-
@refbugs
No guitar special effects have been implemented.
+@seealso
+
+Program reference: @internalsref{Tab_note_heads_engraver}.
@node Chord names
Polyphonic scores consist of many staves. These staves can be
constructed in three different ways:
@itemize @bullet
-@item The group is started with a brace at the left. This is done with the
-@internalsref{GrandStaff} context.
-@item The group is started with a bracket. This is done with the
+@item The group is started with a brace at the left, and bar lines are
+connected. This is done with the @internalsref{GrandStaff} context.
+
+@item The group is started with a bracket, and bar lines are connected. This is done with the
@internalsref{StaffGroup} context
-@item The group is started with a vertical line. This is the default
-for the score.
+
+
+@item The group is started with a vertical line. Bar lines are not
+connected. This is the default for the score.
+
@end itemize
@cindex Staff, multiple
c1
@end lilypond
-In this case, during line breaks, marks must also be printed at the
-end of the line, and not at the beginning. Use the following to force
-that behavior:
+In the case of a line break, marks must also be printed at the end of
+the line, and not at the beginning. Use the following to force that
+behavior:
@example
\override Score.RehearsalMark
#'break-visibility = #begin-of-line-invisible
This can be achieved by setting @internalsref{Staff}.@code{instrument}
and @internalsref{Staff}.@code{instr}. This will print a string before
the start of the staff. For the first start, @code{instrument} is
-used, for the next ones @code{instr} is used:
+used, for the next ones @code{instr} is used.
@quotation
-@lilypond[verbatim,raggedright]
- \set Staff.instrument = "ploink " { c''4 }
+@lilypond[verbatim,raggedright,relative=2]
+ \set Staff.instrument = "Ploink "
+ \set Staff.instr = "Plk "
+ c1
+ \break
+ c''
@end lilypond
@end quotation
You can also use markup texts to construct more complicated instrument
-names:
+names, for example
@quotation
@lilypond[fragment,verbatim,raggedright]
\transpose a c @dots{}
@end example
-Since @var{from} and @var{to} are pitches, @code{\transpose} must be
+Since @var{from} and @var{to} are pitches, so @code{\transpose} must be
inside a @code{\notes} section. @code{\transpose} distinguishes
between enharmonic pitches: both @code{\transpose c cis} or
@code{\transpose c des} will transpose up half a tone. The first
@lilypond[verbatim,raggedright,fragment,relative=1]
\new Staff \partcombine
{
- g a( b) r
+ g g a( b) c c r r
}
{
- g r4 r f
+ g g r4 r e e g g
}
@end lilypond
}
@end lilypond
-The first page shows all staves in full. If they should be removed
-from the first page too, set @code{remove-first} to false
-in @internalsref{RemoveEmptyVerticalGroup}.
+The first page shows all staves in full. If empty staves should be
+removed from the first page too, set @code{remove-first} to false in
+@internalsref{RemoveEmptyVerticalGroup}.
Another application is making ossia sections, i.e. alternative
melodies on a separate piece of staff, with help of a Frenched
@cindex Petrucci
@cindex mensural
-@c [TODO: write more comprehensive introduction on ancient notation]
-
-Support for ancient notation is still under heavy development.
-Regardless of all of the current limitations (see the bugs section
-below for details), it includes features for mensural
-notation and Gregorian Chant notation. There is also limited support
-for figured bass notation.
+Support for ancient notation includes features for mensural notation
+and Gregorian Chant notation. There is also limited support for
+figured bass notation.
Many graphical objects provide a @code{style} property, see
@ref{Ancient note heads}, @ref{Ancient accidentals}, @ref{Ancient
specific notation flavor without need for introducing any new
notational concept.
-
Other aspects of ancient notation can not that easily be expressed as
in terms of just changing a style property of a graphical object.
Therefore, some notational concepts are introduced specifically for
@end multitable
-@c --- This should go somewhere else: ---
-@c @item modern style percussion clef (glyph: @code{clefs-percussion})
-@c
-@c Supported clefs:
-@c @code{percussion}
-@c
-@c @lilypond{\override Staff.TimeSignature #'transparent = ##t \clef "percussion" c'}
-@c
-@c @item modern style tab clef (glyph: @code{clefs-tab})
-@c
-@c Supported clefs:
-@c @code{tab}
-@c
-@c @lilypond{\context Staff \outputproperty #(make-type-checker 'staff-symbol-interface) #'line-count = #6 \override Staff.TimeSignature #'transparent = ##t \clef "tab" c'}
+
@emph{Modern style} means ``as is typeset in contemporary editions of
transcribed mensural music''.
@seealso
-In this manual: for the percussion clef, see @ref{Percussion staves}.
-For the @code{TAB} clef, see @ref{Tablatures}.
-
-Program reference: for modern clefs, see @ref{Clef}.
+In this manual: see @ref{Clef}.
@refbugs
-The mensural g clef is temporarily mapped to the Petrucci g clef,
-until a new mensural g clef will have been implemented.
+The mensural g clef is mapped to the Petrucci g clef, until a new
+mensural g clef is implemented.
@refbugs
-Mensural signature glyphs are mapped to time fractions in a
-hard-wired way. This mapping is sensible, but still arbitrary: given
-a mensural time signature, the time fraction represents a modern meter
-that usually will be a good choice when transcribing a mensural piece
-of music. For a particular piece of mensural music, however, the
-mapping may be unsatisfactory. In particular, the mapping assumes a
-fixed transcription of durations (e.g. brevis = half note in 2/2,
-i.e. 4:1). Some glyphs (such as the alternate glyph for 6/8 meter)
-are not at all accessible through the @code{\time} command.
+Mensural signature glyphs are mapped to time fractions in a hard-wired
+way. This mapping is sensible, but still arbitrary: given a mensural
+time signature, the time fraction represents a modern meter that
+usually will be a good choice when transcribing a mensural piece of
+music. For a particular piece of mensural music, however, the mapping
+may be unsatisfactory. In particular, the mapping assumes a fixed
+transcription of durations (e.g. brevis = half note in 2/2, i.e. 4:1).
+Some glyphs (such as the alternate glyph for 6/8 meter) are not at all
+accessible through the @code{\time} command.
Mensural time signatures are supported typographically, but not yet
musically. The internal representation of durations is
like the @emph{editio vaticana}. There are different custos glyphs
used in different flavors of notational style.
-
For typesetting custodes, just put a @internalsref{Custos_engraver} into the
@internalsref{Staff} context when declaring the @code{\paper} block,
as shown in the following example:
The result looks like this:
-@lilypond
+@lilypond[raggedright]
\score {
\notes {
a'1
- \override Staff.Custos #'style = #'mensural
+ \override Staff.Custos #'style = #'mensural
\break
g'
}
\StaffContext
\consists Custos_engraver
}
- linewidth = 4.0\cm
}
}
@end lilypond
@lilypond
\score {
- \notes {
- \fatText
- s
- ^\markup {
+ \new Lyrics \lyrics {
+ \markup {
\column <
"vaticana"
{ " " \musicglyph #"custodes-vaticana-u0" }
- >
- \column <
+ > }
+ \markup { \column <
"medicaea"
{ " " \musicglyph #"custodes-medicaea-u0" }
- >
+ >}
+ \markup {
\column <
"hufnagel"
{ " " \musicglyph #"custodes-hufnagel-u0" }
- >
+ >}
+ \markup {
\column <
"mensural"
{ " " \musicglyph #"custodes-mensural-u0" }
- >
+ >}
}
- }
+
\paper {
raggedright = ##t
- interscoreline = 1
- \context {
- \ScoreContext
- \remove "Bar_number_engraver"
- }
- \context{
- \StaffContext
- \remove "Clef_engraver"
- \remove "Key_engraver"
- \remove "Time_signature_engraver"
- \remove "Staff_symbol_engraver"
- minimumVerticalExtent = ##f
- }
- }
+ }
}
@end lilypond
-If the boolean property @code{adjust-if-on-staffline} is set to
-@code{#t} (which it is by default), lily typesets slightly different
-variants of the custos glyph, depending on whether the custos, is
-typeset on or between staff lines. The glyph will
-optically fit well into the staff, with the appendage on the right of
-the custos always ending at the same vertical position between two
-staff lines regardless of the pitch. If you set
-@code{adjust-if-on-staffline} to @code{#f}, then
-a compromise between both forms is used.
-
-Just like stems can be attached to note heads in two directions
-@emph{up} and @emph{down}, each custos glyph is available with its
-appendage pointing either up or down. If the pitch of a custos is
-above a selectable position, the appendage will point downwards; if
-the pitch is below this position, the appendage will point upwards.
-Use property @code{neutral-position} to select this position. By
-default, it is set to @code{0}, such that the neutral position is the
-center of the staff. Use property @code{neutral-direction} to control
-what happens if a custos is typeset on the neutral position itself.
-By default, this property is set to @code{-1}, such that the appendage
-will point downwards. If set to @code{1}, the appendage will point
-upwards. Other values such as @code{0} are reserved for future
-extensions and should not be used.
-
@seealso
Program reference: @internalsref{Custos}.
@c TODO: Should double check if I recalled things correctly when I wrote
@c down the following paragraph by heart.
-In musical terminology, a ligature is a coherent graphical symbol that
-represents at least two distinct notes. Ligatures originally appeared
-in the manuscripts of Gregorian chant notation roughly since the 9th
-century as an allusion to the accent symbols of Greek lyric poetry to
-denote ascending or descending sequences of notes. Both, the shape
-and the exact meaning of ligatures changed tremendously during the
-following centuries: In early notation, ligatures were used for
-monophonic tunes (Gregorian chant) and very soon denoted also the way
-of performance in the sense of articulation. With upcoming
-multiphony, the need for a metric system arised, since multiple voices
-of a piece have to be synchronized some way. New notation systems
-were invented that used the manifold shapes of ligatures to now denote
-rhythmical patterns (e.g. black mensural notation, mannered notation,
-ars nova). With the invention of the metric system of the white
-mensural notation, the need for ligatures to denote such patterns
-disappeared. Nevertheless, ligatures were still in use in the
-mensural system for a couple of decades until they finally disappeared
-during the late 16th / early 17th century. Still, ligatures have
-survived in contemporary editions of Gregorian chant such as the
-Editio Vaticana from 1905/08.
-
-
-Syntactically, ligatures are simply enclosed by @code{\[} and
-@code{\]}. Some ligature styles (such as Editio Vaticana) may need
-additional input syntax specific for this particular type of ligature.
-By default, the @internalsref{LigatureBracket} engraver just puts a
-square bracket above the ligature:
+A ligature is a coherent graphical symbol that represents at least two
+distinct notes. Ligatures originally appeared in the manuscripts of
+Gregorian chant notation roughly since the 9th century to denote
+ascending or descending sequences of notes.
+
+Ligatures are entered by enclosing them in @code{\[} and @code{\]}.
+Some ligature styles may need additional input syntax specific for
+this particular type of ligature. By default, the
+@internalsref{LigatureBracket} engraver just puts a square bracket
+above the ligature:
@lilypond[raggedright,verbatim]
\score {
To select a specific style of ligatures, a proper ligature engraver
has to be added to the @internalsref{Voice} context, as explained in
the following subsections. Only white mensural ligatures
-are supported with certain limitations. Support for Editio Vaticana
-will be added in the future.
+are supported with certain limitations.
@menu
* White mensural ligatures::
@cindex Mensural ligatures
@cindex White mensural ligatures
-There is limited support for white mensural ligatures. The
-implementation is still experimental; it may output strange
-warnings or even crash in some cases or produce weird results on more
-complex ligatures.
-
+There is limited support for white mensural ligatures.
To engrave white mensural ligatures, in the paper block the
@internalsref{Mensural_ligature_engraver} has to be put into the
}
@end lilypond
+@refbugs
+
+The implementation is experimental; it may output strange warnings or
+even crash in some cases or produce weird results on more complex
+ligatures.
@node Gregorian square neumes ligatures
@subsubsection Gregorian square neumes ligatures
+++ /dev/null
-#!@PYTHON@
-
-# PMX is a Musixtex preprocessor written by Don Simons, see
-# http://www.gmd.de/Misc/Music/musixtex/software/pmx/
-
-# TODO:
-# * block openings aren't parsed.
-
-import os
-import string
-import sys
-import re
-import getopt
-
-program_name = 'pmx2ly'
-version = '@TOPLEVEL_VERSION@'
-if version == '@' + 'TOPLEVEL_VERSION' + '@':
- version = '(unknown version)' # uGUHGUHGHGUGH
-
-
-def encodeint (i):
- return chr ( i + ord ('A'))
-
-
-actab = {-2: 'eses', -1: 'es', 0 : '', 1: 'is', 2:'isis'}
-
-def pitch_to_lily_string (tup):
- (o,n,a) = tup
-
- nm = chr((n + 2) % 7 + ord ('a'))
- nm = nm + actab[a]
- if o > 0:
- nm = nm + "'" * o
- elif o < 0:
- nm = nm + "," * -o
- return nm
-
-def gcd (a,b):
- if b == 0:
- return a
- c = a
- while c:
- c = a % b
- a = b
- b = c
- return a
-
-def rat_simplify (r):
- (n,d) = r
- if d < 0:
- d = -d
- n = -n
- if n == 0:
- return (0,1)
- else:
- g = gcd (n, d)
- return (n/g, d/g)
-
-def rat_multiply (a,b):
- (x,y) = a
- (p,q) = b
-
- return rat_simplify ((x*p, y*q))
-
-def rat_divide (a,b):
- (p,q) = b
- return rat_multiply (a, (q,p))
-
-tuplet_table = {
- 2: 3,
- 3: 2,
- 5: 4
-}
-
-
-def rat_add (a,b):
- (x,y) = a
- (p,q) = b
-
- return rat_simplify ((x*q + p*y, y*q))
-
-def rat_neg (a):
- (p,q) = a
- return (-p,q)
-
-
-def rat_larger (a,b):
- return rat_subtract (a, b )[0] > 0
-
-def rat_subtract (a,b ):
- return rat_add (a, rat_neg (b))
-
-def rat_to_duration (frac):
- log = 1
- d = (1,1)
- while rat_larger (d, frac):
- d = rat_multiply (d, (1,2))
- log = log << 1
-
- frac = rat_subtract (frac, d)
- dots = 0
- if frac == rat_multiply (d, (1,2)):
- dots = 1
- elif frac == rat_multiply (d, (3,4)):
- dots = 2
- return (log, dots)
-
-
-class Barcheck :
- def __init__ (self):
- pass
- def dump (self):
- return '|\n'
-
-
-class Meter :
- def __init__ (self,nums):
- self.nums = nums
- def dump (self):
- return ' %{ FIXME: meter change %} '
-
-class Beam:
- def __init__ (self, ch):
- self.char = ch
- def dump (self):
- return self.char
-
-class Slur:
- def __init__ (self,id):
- self.id = id
- self.start_chord = None
- self.end_chord = None
- def calculate (self):
- s =self.start_chord
- e= self.end_chord
-
- if e and s:
- s.note_suffix = s.note_suffix + '('
- e.note_prefix = e.note_suffix + ')'
- else:
- sys.stderr.write ("\nOrphaned slur")
-
-
-class Voice:
- def __init__ (self):
- self.entries = []
- self.chords = []
- self.staff = None
- self.current_slurs = []
- self.slurs = []
- def toggle_slur (self, id):
-
- for s in self.current_slurs:
- if s.id == id:
- self.current_slurs.remove (s)
- s.end_chord = self.chords[-1]
- return
- s = Slur (id)
- s.start_chord = self.chords[-1]
- self.current_slurs.append (s)
- self.slurs.append (s)
-
- def last_chord (self):
- return self.chords[-1]
-
- def add_chord (self, ch):
- self.chords.append (ch)
- self.entries.append (ch)
- def add_nonchord (self, nch):
- self.entries.append (nch)
-
- def idstring (self):
- return 'staff%svoice%s ' % (encodeint (self.staff.number) , encodeint(self.number))
- def dump (self):
- str = ''
- ln = ''
- for e in self.entries:
- next = ' ' + e.dump ()
- if next[-1] == '\n':
- str = str + ln + next
- ln = ''
- continue
-
- if len (ln) +len (next) > 72:
- str = str+ ln + '\n'
- ln = ''
- ln = ln + next
-
-
- str = str + ln
- id = self.idstring ()
-
- str = '%s = \\notes { \n %s }\n '% (id, str)
- return str
- def calculate_graces (self):
- lastgr = 0
- lastc = None
- for c in self.chords:
- if c.grace and not lastgr:
- c.chord_prefix = c.chord_prefix + '\\grace { '
- elif not c.grace and lastgr:
- lastc.chord_suffix = lastc.chord_suffix + ' } '
- lastgr = c.grace
- lastc = c
- def calculate (self):
- self.calculate_graces ()
- for s in self.slurs:
- s.calculate ()
-
-class Clef:
- def __init__ (self, cl):
- self.type = cl
- def dump(self):
- return '\\clef %s' % self.type
-
-class Key:
- def __init__ (self, key):
- self.type = key
- def dump(self):
- return '\\key %s' % self.type
-
-clef_table = {
- 'b':'bass' ,
- 'r':'baritone',
- 'n':'tenor',
- 'a':'alto',
- 'm':'mezzosoprano',
- 's':'soprano',
- 't':'treble',
- 'f':'frenchviolin',
- }
-key_table = {
- '+0':'c \major',
- '+1':'g \major',
- '+2':'d \major',
- '+3':'a \major',
- '+4':'e \major',
- '+5':'b \major',
- '+6':'fis \major',
- '-1':'f \major',
- '-2':'bes \major',
- '-3':'ees \major',
- '-4':'aes \major',
- '-5':'des \major',
- '-6':'ges \major'
- }
-class Staff:
- def __init__ (self):
- self.voices = (Voice (), Voice())
- self.clef = None
- self.instrument = 0
- self.voice_idx = 0
- self.number = None
- self.key = 0
-
- i = 0
- for v in self.voices:
- v.staff = self
- v.number = i
- i = i+1
- def set_clef (self, letter):
- if clef_table.has_key (letter):
- clstr = clef_table[letter]
- self.voices[0].add_nonchord (Clef (clstr))
- else:
- sys.stderr.write ("Clef type `%c' unknown\n" % letter)
-
- def current_voice (self):
- return self.voices[self.voice_idx]
- def next_voice (self):
- self.voice_idx = (self.voice_idx + 1)%len (self.voices)
-
- def calculate (self):
- for v in self.voices:
- v.calculate ()
- def idstring (self):
- return 'staff%s' % encodeint (self.number)
- def dump (self):
- str = ''
-
- refs = ''
- for v in self.voices:
- str = str + v.dump()
- refs = refs + '\\' + v.idstring ()+ ' '
-
- str = str + '\n\n%s = \\context Staff = %s \n << \n %s >>\n\n\n'% (self.idstring (), self.idstring (), refs)
- return str
-
-class Tuplet:
- def __init__ (self, number, base, dots):
- self.chords = []
- self.number = number
- self.replaces = tuplet_table[number]
- self.base = base
- self.dots = dots
-
- length = (1,base)
- if dots == 1:
- length = rat_multiply (length, (3,2))
- elif dots == 2:
- length = rat_multiply (length, (7,4))
-
- length = rat_multiply (length, (1,self.replaces))
-
- (nb,nd) =rat_to_duration (length)
-
- self.note_base = nb
- self.note_dots = nd
-
- def add_chord (self, ch):
- ch.dots = self.note_dots
- ch.basic_duration = self.note_base
- self.chords.append (ch)
-
- if len (self.chords) == 1:
- ch.chord_prefix = '\\times %d/%d { ' % (self.replaces, self.number)
- elif len (self.chords) == self.number:
- ch.chord_suffix = ' }'
-
-class Chord:
- def __init__ (self):
- self.pitches = []
- self.dots = 0
- self.basic_duration = 0
- self.scripts = []
- self.grace = 0
- self.chord_prefix = ''
- self.chord_suffix = ''
- self.note_prefix = ''
- self.note_suffix = ''
-
- def dump (self):
- str = ''
-
- sd = ''
- if self.basic_duration == 0.5:
- sd = '\\breve'
- else:
- sd = '%d' % self.basic_duration
- sd = sd + '.' * self.dots
- for p in self.pitches:
- if str:
- str = str + ' '
- str = str + pitch_to_lily_string (p)
-
- if len (self.pitches) > 1:
- str = '<%s>' % str
- elif len (self.pitches) == 0:
- str = 'r'
-
- str = str + sd
- for s in self.scripts:
- str = str + '-' + s
-
- str = self.note_prefix + str + self.note_suffix
- str = self.chord_prefix + str + self.chord_suffix
-
- return str
-
-SPACE=' \t\n'
-DIGITS ='0123456789'
-basicdur_table = {
- 9: 0.5,
- 0: 0 ,
- 2: 2 ,
- 4: 4 ,
- 8: 8 ,
- 1: 16,
- 3: 32,
- 6: 64
- }
-
-
-ornament_table = {
- 't': '\\prall',
- 'm': '\\mordent',
- 'x': '"x"',
- '+': '+',
- 'u': '"pizz"',
- 'p': '|',
- '(': '"paren"',
- ')': '"paren"',
- 'g': '"segno"',
- '.': '.',
- 'fd': '\\fermata',
- 'f': '\\fermata',
- '_': '-',
- 'T': '\\trill',
- '>': '>',
- '^': '^',
- }
-
-class Parser:
- def __init__ (self, filename):
- self.staffs = []
- self.forced_duration = None
- self.last_name = 0
- self.last_oct = 0
- self.tuplets_expected = 0
- self.tuplets = []
- self.last_basic_duration = 4
-
- self.parse (filename)
-
- def set_staffs (self, number):
- self.staffs = map (lambda x: Staff (), range(0, number))
-
- self.staff_idx = 0
-
- i =0
- for s in self.staffs:
- s.number = i
- i = i+1
- def current_staff (self):
- return self.staffs[self.staff_idx]
-
- def current_voice (self):
- return self.current_staff ().current_voice ()
-
- def next_staff (self):
- self.staff_idx = (self.staff_idx + 1)% len (self.staffs)
-
- def parse_note (self, str):
- name = None
- ch = None
-
- grace = 0
- if str[0] == 'G':
- grace = 1
- str = str[1:]
-
- if str[0] == 'z':
- ch = self.current_voice().last_chord()
- str = str[1:]
- else:
- ch = Chord ()
- self.current_voice().add_chord (ch)
-
- # what about 's'?
- if str[0] <> 'r':
- name = (ord (str[0]) - ord('a') + 5) % 7
-
- str = str[1:]
-
- ch.grace = ch.grace or grace
-
- forced_duration = 0
- alteration = 0
- dots = 0
- oct = None
- durdigit = None
- multibar = 0
- tupnumber = 0
- extra_oct = 0
- while str[0] in 'dsfmnul0123456789.,+-':
- c = str[0]
- str = str[1:]
- if c == 'f':
- alteration = alteration -1
- elif c == 'n':
- alteration = 0
- elif c == 'm':
- multibar = 1
- elif c == 's':
- alteration = alteration +1
- elif c == 'd':
- dots = dots + 1
- elif c in DIGITS and durdigit == None and \
- self.tuplets_expected == 0:
- durdigit = string.atoi (c)
- elif c in DIGITS:
- oct = string.atoi (c) - 3
- elif c == '+':
- extra_oct = extra_oct + 1
- elif c == '-':
- extra_oct = extra_oct - 1
- elif c == '.':
- dots = dots+ 1
- forced_duration = 2
- elif c == ',':
- forced_duration = 2
-
- if str[0] == 'x':
- str = str[1:]
- tupnumber = string.atoi (str[0])
- str = str[1:]
- str=re.sub (r'^n?f?[+-0-9.]+', '' , str)
-
-
- if durdigit:
- try:
- basic_duration = basicdur_table[durdigit]
- self.last_basic_duration = basic_duration
- except KeyError:
- sys.stderr.write ("""
-Huh? expected duration, found %d Left was `%s'""" % (durdigit, str[:20]))
-
- basic_duration = 4
- else:
- basic_duration = self.last_basic_duration
-
-
-
- if name <> None and oct == None:
- e = 0
- if self.last_name < name and name -self.last_name > 3:
- e = -1
- elif self.last_name > name and self.last_name -name > 3:
- e = 1
-
- oct = self.last_oct +e + extra_oct
-
- if name <> None:
- self.last_oct = oct
- self.last_name = name
-
- if name <> None:
- ch.pitches.append ((oct, name, alteration))
-
- # do before adding to tuplet.
- ch.basic_duration = basic_duration
- ch.dots = dots
-
- if forced_duration:
- self.forced_duration = ch.basic_duration / forced_duration
-
- if tupnumber:
- tup =Tuplet (tupnumber, basic_duration, dots)
- self.tuplets_expected = tupnumber
- self.tuplets.append (tup)
-
- if self.tuplets_expected > 0:
- self.tuplets[-1].add_chord (ch)
- self.tuplets_expected = self.tuplets_expected - 1
-
- return str
- def parse_basso_continuo (self, str):
- while str[0] in DIGITS +'#n-':
- scr = str[0]
-
- if scr == '#':
- scr = '\\\\textsharp'
-
- if len(scr)>1 or scr not in DIGITS:
- scr = '"%s"' % scr
-
- self.current_voice().last_chord ().scripts.append (scr)
- str=str[1:]
- return str
- def parse_beams (self,str):
- c = str[0]
- # self.current_voice().add_nonchord (Beam(c))
- if str[0] == '[':
- str = str[1:]
- while str[0] in '+-0123456789':
- str=str[1:]
- else:
- str = str[1:]
-
- return str
-
- def parse_key (self, str):
- key = ""
- #The key is changed by a string of the form K[+-]<num>[+-]<num>
- #where the first number is the transposition and the second number is the
- #new key signature. For now, we won't bother with the transposition.
- if str[2] != '0':
- sys.stderr.write("Transposition not implemented yet: ")
- while str[0] in '+-0123456789':
- str = str[1:]
- else:
- str=str[3:]
- key = ''
- while str[0] in '+-0123456789':
- key=key + str[0]
- str=str[1:]
- keystr = key_table[key]
- self.current_voice().add_nonchord (Key(keystr))
- return(str)
-
-
- def parse_header (self, ls):
- def atonum(a):
- if re.search('\\.', a):
- return string.atof (a)
- else:
- return string.atoi (a)
-
- number_count = 12
- numbers = []
-
- while len (numbers) < number_count:
- opening = ls[0]
- ls = ls[1:]
-
- opening = re.sub ('[ \t\n]+', ' ', opening)
- opening = re.sub ('^ ', '', opening)
- opening = re.sub (' $', '', opening)
- if opening == '':
- continue
- opening = string.split (opening, ' ')
-
- numbers = numbers + map (atonum, opening)
-
- (no_staffs, no_instruments, timesig_num, timesig_den, ptimesig_num,
- esig_den, pickup_beats,keysig_number) = tuple (numbers[0:8])
- (no_pages,no_systems, musicsize, fracindent) = tuple (numbers[8:])
-
- # ignore this.
- # opening = map (string.atoi, re.split ('[\t ]+', opening))
-
- instruments = []
- while len (instruments) < no_instruments:
- instruments.append (ls[0])
- ls = ls[1:]
-
- l = ls[0]
- ls = ls[1:]
-
- self.set_staffs (no_staffs)
-
- for s in self.staffs:
- s.set_clef(l[0])
- l = l[1:]
-
- # dump path
- ls = ls[1:]
-
- # dump more ?
- return ls
-
- def parse_ornament (self, left):
- left = left[1:]
- e = self.current_voice ().last_chord ()
-
- id = left[0]
- left = left[1:]
- if left[0] == 'd':
- id = id +'d'
- left = left [1:]
-
- orn = '"orn"'
- try:
- orn = ornament_table[id]
- except KeyError:
- sys.stderr.write ("unknown ornament `%s'\n" % id)
-
- e.scripts.append (orn)
- return left
- def parse_barcheck (self, left):
- self.current_voice ().add_nonchord (Barcheck ())
-
- return left [1:]
-
- def parse_slur (self, left):
- left = left[1:]
-
- id = None
-
- if re.match ('[A-Z0-9]', left[0]):
- id = left[0]
- left= left[1:]
- while left[0] in 'uld0123456789+-.':
- left= left[1:]
-
- self.current_voice ().toggle_slur (id)
- return left
-
- def parse_mumbo_jumbo (self,left):
- left = left[1:]
- while left and left[0] <> '\\':
- left = left[1:]
-
- left = left[1:]
- return left
- def parsex (self,left):
- left = left[1:]
- while left[0] in DIGITS:
- left = left[1:]
-
- return left
-
- def parse_body (self, left):
- preamble = 1
-
- while left:
- c = left[0]
- if c == '%':
- f = string.find (left, '\n')
- if f < 0:
- left = ''
- left = left[f+1:]
- elif c == 'm':
- left = left[1:]
- m = re.match ('([o0-9]/[o0-9]/[o0-9]/[o0-9])', left)
- if m:
- nums = m.group (1)
- left = left[len (nums):]
- nums = map (string.atoi , nums)
- self.current_voice ().add_nonchord (Meter (nums))
- continue
-
- m= re.match ('([0-9o]+)', left)
- if m:
- nums = m.group (1)
- self.current_voice ().add_nonchord (Meter (map (string.atoi (nums))))
- continue
-
- elif left[0] in 'lh':
- f = string.find (left, '\n')
- if f <0 :
- left = ''
- else:
- left = left[f+1:]
-
- f = string.find (left, '\n')
- title = left[:f]
- left=left[f+1:]
- elif c in 'Gzabcdefgr':
- left = self.parse_note (left)
- elif c in DIGITS + 'n#-':
- left = self.parse_basso_continuo (left)
- elif c in SPACE:
- left = left[1:]
- elif c == 's':
- left = self.parse_slur (left)
- elif c == '|':
- left = self.parse_barcheck (left)
- elif c == 'o':
- left = self.parse_ornament (left)
- elif c == 'x':
- left = self.parsex (left)
- elif c == 'C':
- self.current_staff().set_clef(str(left[1]))
- left = left[2:]
- elif c == 'K':
- left = self.parse_key (left)
- elif c in "[]":
- left = self.parse_beams (left)
- elif left[:2] == "//":
- self.current_staff().next_voice ()
- left = left[2:]
- elif c == '/':
- self.next_staff ()
- left = left[1:]
- elif c == '\\':
- left = self.parse_mumbo_jumbo(left)
- elif c == '\r':
- left = left[1:]
- else:
- sys.stderr.write ("""
-Huh? Unknown directive `%s', before `%s'""" % (c, left[:20] ))
- left = left[1:]
-
- def dump (self):
- str = ''
-
- refs = ''
- for s in self.staffs:
- str = str + s.dump ()
- refs = '\\' + s.idstring() + refs
-
- str = str + "\n\n\\score { <<\n %s\n >> }" % refs
- return str
-
-
- def parse (self,fn):
- ls = open (fn).readlines ()
- def subst(s):
- return re.sub ('%.*$', '', s)
-
- ls = map (subst, ls)
- ls = filter (lambda x: x <> '\n', ls)
- ls = self.parse_header (ls)
- left = string.join (ls, ' ')
-
-# print left
- self.parse_body (left)
- for c in self.staffs:
- c.calculate ()
-
-
-
-
-
-def help ():
- sys.stdout.write (
-"""Usage: pmx2ly [OPTIONS]... PMX-FILE
-
-Convert PMX to LilyPond.
-
-Options:
- -h, --help print this help
- -o, --output=FILE set output filename to FILE
- -v, --version shown version information
-
-PMX is a Musixtex preprocessor written by Don Simons, see
-http://www.gmd.de/Misc/Music/musixtex/software/pmx/.
-
-Report bugs to bug-lilypond@gnu.org.
-
-Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
-
-""")
-
-
-def print_version ():
- sys.stdout.write ("""pmx2ly (GNU LilyPond) %s
-
-This is free software. It is covered by the GNU General Public License,
-and you are welcome to change it and/or distribute copies of it under
-certain conditions. Invoke as `midi2ly --warranty' for more information.
-
-Copyright (c) 2000--2004 by Han-Wen Nienhuys <hanwen@cs.uu.nl>
-""" % version)
-def identify():
- sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
-
-
-
-(options, files) = getopt.getopt (sys.argv[1:], 'vo:h', ['help','version', 'output='])
-out_filename = None
-for opt in options:
- o = opt[0]
- a = opt[1]
- if o== '--help' or o == '-h':
- help ()
- sys.exit (0)
- if o == '--version' or o == '-v':
- print_version ()
- sys.exit(0)
-
- if o == '--output' or o == '-o':
- out_filename = a
- else:
- print o
- raise getopt.error
-
-identify()
-
-for f in files:
- if f == '-':
- f = ''
-
- sys.stderr.write ('Processing `%s\'\n' % f)
- e = Parser(f)
- if not out_filename:
- out_filename = os.path.basename (re.sub ('(?i).pmx$', '.ly', f))
-
- if out_filename == f:
- out_filename = os.path.basename (f + '.ly')
-
- sys.stderr.write ('Writing `%s\'' % out_filename)
- ly = e.dump()
-
-
-
- fo = open (out_filename, 'w')
- fo.write ('%% lily was here -- automatically converted by pmx2ly from %s\n' % f)
- fo.write(ly)
- fo.close ()
-
-