* Music notation::
* Polyphony::
* Spanners::
+* Ornaments::
* Repeats::
* Piano music::
* Lyrics::
@cindex @code{keySignature}
-@c . {Clef changes}
-@subsubsection Clef changes
+@c . {Clef}
+@subsection Clef changes
@cindex @code{\clef}
@example
\clef @var{clefname} @code{;}
* Beam::
* Slur ::
* Phrasing slur::
-* Ornaments::
-* Grace notes::
-* Bar check::
@end menu
@c . {Ornaments}
@node Ornaments
-@subsection Ornaments
+@section Ornaments
@cindex Ornaments
@menu
* Articulation::
* Text scripts::
+* Grace notes::
+* Bar check::
@end menu
@c . {Articulation}
@node Articulation
-@subsubsection Articulation
+@subsection Articulation
@cindex Articulation
@cindex articulations
@end lilypond
-@c . {Text scripts}
+@c . {Text scripts}
@node Text scripts
-@subsubsection Text scripts
+@subsection Text scripts
@cindex Text scripts
In addition, it is possible to place arbitrary strings of text or markup
MIDI rendering of the music.
@c . {Fingerings}
-@unnumberedsubsubsec Fingerings
+@subsubsection Fingerings
@cindex Fingerings
To save typing, fingering instructions (digits 0 to 9 are
@node Automatic part combining
@subsection Automatic part combining
+@cindex automatic part combining
+@cindex part combiner
-[TODO]
+You will already have seen that LilyPond can combine several Threads
+into one Voice, and put several Voices onto one Staff. The automatic
+part combiner takes this a step further. Two parts of music can be
+combined together in an intelligent way, ie, when the two parts are
+identical for a period of time, only one can be showed. In places where
+the two parts differ, stem directions can be set automatically. That is
+why the part combiner is of great use for the typesetting of Hymns and
+orchestral scores.
+
+
+@subsubsection Part combine syntax
+
+The syntax for part combining is
+
+@example
+ \partcombine @var{context} @var{musicexpr1} @var{musicexpr2}
+@end example
+
+where the pieces of music @var{musicexpr1} and @var{musicexpr2} will be
+combined into one context @var{context}. The names of the music
+expressions must start with the prefixes @code{one} and @code{two}.
+
+@subsubsection Part combine usage
+
+@cindex @code{Thread_devnull_engraver}
+@cindex @code{Voice_engraver}
+@cindex @code{A2_engraver}
+
+The most useful function of the part combiner to combining threads into
+one voice, as common for wind parts in orchestral scores:
+
+@lilypond[verbatim,singleline,fragment]
+ \context Staff <
+ \context Voice=one \partcombine Voice
+ \context Thread=one \notes\relative c'' {
+ g a b r
+ }
+ \context Thread=two \notes\relative c'' {
+ g r2 f4
+ }
+ >
+@end lilypond
+
+If you have developed a bit of a feel for LilyPond's functioning, you
+will notice that what you see above is quite unusual. The first
+@code{g} appears only once, although it was specified twice (once in
+each Thread). That is the work of the
+@code{Thread_devnull_engraver}@footnote{On unix systems, the file
+@file{/dev/null} is special device: anything written to it is
+discarded.}, that works closely together with the part combiner. When
+the part combiner notices that two threads are identical, it tells the
+@code{Thread_devnull_engraver} to discard everything in the second
+thread.
+
+Similarly, the markings @emph{@`{a}2}, @emph{Solo} and @emph{Solo II},
+are created by the @code{A2_engraver}. The @code{A2_engraver} also acts
+upon instructions of the part combiner. Another thing that the
+@code{A2_engraver} does, is forcing of stem, slur and tie directions,
+always when both threads are not identical; up for the musicexpr called
+@code{one}, down for the musicexpr called @code{two}.
+
+There is actually a third engraver involved in part combining; the
+@code{Voice_devnull_engraver}. This one takes care of removing
+redundant spanners such as beams, slurs, ties, crescendi, etc.
+
+If you just want the splitting of Threads and setting of directions, and
+not the textual markings, you may set the property @var{soloADue} to false:
+
+@lilypond[verbatim,singleline]
+ \score {
+ \notes \context Staff <
+ \context Voice=one \partcombine Voice
+ \context Thread=one\relative c'' {
+ b4 a c g
+ }
+ \context Thread=two\relative c'' {
+ d,2 a4 g'
+ }
+ >
+ \paper{
+ \translator {
+ \VoiceContext
+ soloADue = ##f
+ } }
+ }
+}
+@end lilypond
+
+There are a number of other properties that you can use to tweak the
+behavior of part combining, refer to the automatically generated
+documentation of the involved engravers and the examples in the tutorial.
@c . {Custodes}
\paper block. Translation modules for sound are called performers.
The contexts for MIDI output are defined in @file{ly/performer.ly}.
+[Volume control]
+[Instrument Equaliser]
+
+FIXME: would it be useful to refer to files like scm/midi.scm,
+or to give examples of how to tweak MIDI output volume?
+
@c . {MIDI instrument names}
@node MIDI instrument names
* AsciiScript: ASCII-art output
* Translations into Japanese, French and Russian
+
+* EZ play notation
SCM ly_quote_scm (SCM s);
SCM ly_type (SCM);
bool type_check_assignment (SCM val, SCM sym, SCM type_symbol) ;
+SCM ly_number2string (SCM s);
/*
display and print newline.
gh_double2scm (height),
SCM_UNDEFINED));
- /*
- all elements.
- */
- for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s); s = gh_cdr (s))
- {
- Grob *sc = unsmob_grob (gh_car (s));
- Molecule *m = sc->get_molecule ();
- if (!m)
- continue;
-
- Offset o (sc->relative_coordinate (this, X_AXIS),
- sc->relative_coordinate (this, Y_AXIS));
-
- SCM e = sc->get_grob_property ("extra-offset");
- if (gh_pair_p (e))
- {
- o[X_AXIS] += gh_scm2double (gh_car (e));
- o[Y_AXIS] += gh_scm2double (gh_cdr (e));
- }
-
- output_molecule (m->get_expr (), o);
- }
+ /* Output elements in three layers, 0, 1, 2.
+ The default layer is 1. */
+ for (int i = 0; i < 3; i++)
+ for (SCM s = get_grob_property ("all-elements"); gh_pair_p (s);
+ s = gh_cdr (s))
+ {
+ Grob *sc = unsmob_grob (gh_car (s));
+ Molecule *m = sc->get_molecule ();
+ if (!m)
+ continue;
+
+ SCM s = sc->get_grob_property ("layer");
+ int layer = gh_number_p (s) ? gh_scm2int (s) : 1;
+ if (layer != i)
+ continue;
+
+ Offset o (sc->relative_coordinate (this, X_AXIS),
+ sc->relative_coordinate (this, Y_AXIS));
+
+ SCM e = sc->get_grob_property ("extra-offset");
+ if (gh_pair_p (e))
+ {
+ o[X_AXIS] += gh_scm2double (gh_car (e));
+ o[Y_AXIS] += gh_scm2double (gh_cdr (e));
+ }
+
+ output_molecule (m->get_expr (), o);
+ }
+
if (last_line)
{
output_scheme (gh_list (ly_symbol2scm ("stop-last-line"), SCM_UNDEFINED));
stroke
} bind def
+/difficult_draw_ez_ball % ch letter_col ball_col font
+{
+ % font
+ findfont 0.7 scalefont setfont
+ 0.1 setlinewidth
+ 0 0 moveto
+ 0 setgray
+ 0.5 0 0.5 0 360 arc closepath fill stroke
+ % ball_col
+ 1 eq {
+ 0.01 setlinewidth
+ 1 setgray
+ 0.5 0 0.4 0 360 arc closepath
+ fill stroke
+ } if
+ % letter_col
+ setgray
+ % 0.25 is empiric centering. Change to taste
+ 0.25 -0.25 moveto
+ % ch
+ show
+} bind def
+
+% simple, but does it work everywhere?
+/draw_ez_ball % ch letter_col ball_col font
+{
+ % font
+ findfont 0.85 scalefont setfont
+ /origin { 0.45 0 } def
+ 0 setgray
+ 1.1 setlinewidth
+ origin moveto
+ origin lineto stroke
+ % ball_col
+ setgray
+ 0.9 setlinewidth
+ origin moveto
+ origin lineto stroke
+ % letter_col
+ setgray
+ % 0.25 is empiric centering. Change to taste
+ origin moveto
+ -0.28 -0.30 rmoveto
+ % ch
+ show
+} bind def
+
/draw_volta % h w thick vert_start vert_end
{
/vert_end exch def
For text, this is `relative'(?) to the current alignment.
For barline, space after a thick line.")
+(grob-property-description 'layer number? "The output layer [0..2]. The default is 1.")
(grob-property-description 'left-padding number? "space left of accs.")
(grob-property-description 'length number? "Stem length for unbeamed stems, only for user override.")
(grob-property-description 'lengths list? "Stem length given multiplicity of flag.")
(grob-property-description 'no-spacing-rods boolean? "read from grobs: boolean that makes Separation_item ignore this item (MOVE ME TO ITEM).")
(grob-property-description 'no-stem-extend boolean? "should stem not be extended to middle staff line?.")
(grob-property-description 'non-default boolean? "not set because of existence of a bar?.")
+(grob-property-description 'note-character string? "character to print in a note head.")
(grob-property-description 'note-width number? "unit for horizontal translation, measured in staff-space.")
(grob-property-description 'number-gap number? "size of the gap for the number in a tuplet.")
(grob-property-description 'old-accidentals list? "list of (pitch, accidental) pairs.")
(ly-warn (string-append
"Programming error: No such font known "
(car name-mag-pair) " "
- (number->string (cdr name-mag-pair))
+ (ly-number->string (cdr name-mag-pair))
))
"") ; issue no command
" { /"
(car name-mag)
" findfont "
- "12 " (number->string (cdr name-mag)) " mul "
+ "12 " (ly-number->string (cdr name-mag)) " mul "
"lilypondpaperoutputscale div scalefont setfont } bind def "
"\n"))
(define (dashed-slur thick dash l)
(string-append
(apply string-append (map control->string l))
- (number->string thick)
+ (ly-number->string thick)
" [ "
- (number->string dash)
+ (ly-number->string dash)
" "
- (number->string (* 10 thick)) ;UGH. 10 ?
+ (ly-number->string (* 10 thick)) ;UGH. 10 ?
" ] 0 draw_dashed_slur"))
(define (dashed-line thick on off dx dy)
(string-append
- (number->string dx)
+ (ly-number->string dx)
" "
- (number->string dy)
+ (ly-number->string dy)
" "
- (number->string thick)
+ (ly-number->string thick)
" [ "
- (number->string on)
+ (ly-number->string on)
" "
- (number->string off)
+ (ly-number->string off)
" ] 0 draw_dashed_line"))
(define (decrescendo thick w h cont)
(define (invoke-dim1 s d)
(string-append
- (number->string (* d (/ 72.27 72))) " " s ))
+ (ly-number->string (* d (/ 72.27 72))) " " s ))
(define (placebox x y s)
(string-append
- (number->string x) " " (number->string y) " {" s "} placebox "))
+ (ly-number->string x) " " (ly-number->string y) " {" s "} placebox\n"))
(define (bezier-sandwich l thick)
(string-append
(apply string-append (map control->string l))
- (number->string thick)
+ (ly-number->string thick)
" draw_bezier_sandwich"))
(define (start-line height)
(define (unknown)
"\n unknown\n")
-;; note heads with letters.
(define (ez-ball ch letter-col ball-col)
- (string-append "
-/Helvetica-Bold findfont
-0.7 scalefont
-setfont
-0.1 setlinewidth
- 0 0 moveto
-0 setgray
-0.5 0 0.5 0 360 arc
-closepath "
- (if (equal? ball-col 0) " fill " " stroke ")
- (number->string letter-col)
- "
-setgray
-% 0.25 is empiric centering. Change to taste
-0.25 -0.25 moveto
- (" ch ") show
-showpage ")
- )
+ (string-append
+ " (" ch ") "
+ (numbers->string (list letter-col ball-col))
+ " /Helvetica-Bold " ;; ugh
+ " draw_ez_ball"))
(define (define-origin a b c ) "")
(define (no-origin) "")