@item @email{bjoern.jacke@@gmx.de, Bjoern Jacke}
German glossary stuff.
@item @email{chris@@fluffhouse.org.uk, Chris Jackson},
- Emacs mode indentation, directed arpeggios.
+ Piano pedals, Emacs mode indentation, directed arpeggios.
@item @email{nj104@@cus.cam.ac.uk, Neil Jerram}.
parts of Documentation/Vocab*
@item @email{heikki.junes@@hut.fi, Heikki Junes}.
@end lilypond
The symbols that are printed can be modified by setting
-@code{pedal@var{X}Strings}, where @var{X} is one of the pedal
-types. Refer to the generated documentation of @rgrob{PianoPedal} for
-more information.
+@code{pedal@var{X}Strings}, where @var{X} is one of the pedal types:
+Sustain, Sostenuto or UnaCorda. Refer to the generated documentation of
+@rgrob{PianoPedal} for more information.
-@refbugs
+Pedals can also be indicated by a sequence of brackets, by setting the
+@code{pedal-type} property of SustainPedal grobs:
+
+@lilypond[fragment,verbatim]
+\property Staff.SustainPedal \override #'pedal-type = #'bracket
+c''4 \sustainDown d''4 e''4 a'4 \sustainUp \sustainDown f'4 g'4 a'4 \sustainUp
+@end lilypond
+
+A third style of pedal notation is a mixture of text and brackets,
+obtained by setting @code{pedal-type} to @code{mixed}:
+@lilypond[fragment,verbatim]
+\property Staff.SustainPedal \override #'pedal-type = #'mixed
+c''4 \sustainDown d''4 e''4 c'4 \sustainUp \sustainDown f'4 g'4 a'4 \sustainUp
+@end lilypond
+
+The default '*Ped' style for sustain and damper pedals corresponds to
+@code{\pedal-type = #'text}. However @code{mixed} is the default style
+for a sostenuto pedal:
-Currently, brackets are not supported, only text markings (i.e. `*Ped'
-style).
+@lilypond[fragment,verbatim]
+c''4 \sostenutoDown d''4 e''4 c'4 f'4 g'4 a'4 \sostenutoUp
+@end lilypond
@c . {Arpeggio}
--- /dev/null
+\version "1.5.38"
+\header{
+texidoc = "Piano pedal symbols merge stop and start. The strings are configurable.
+Text style, bracket style, and a mixture of both are supported. "
+}
+
+
+
+
+\score{
+\context Staff \notes\relative c'{
+
+c4 d e f g
+\sustainDown b c
+c, [d16 c c c] [e e \sustainUp \sustainDown e e ] f4 \sustainUp
+g\sustainDown b \sustainUp c
+\property Staff.pedalSustainStrings = #'("-" "-P" "P")
+\property Staff.SustainPedal \override #'padding = #-2
+c, \sustainDown d e \sustainUp \sustainDown f
+ \sustainUp g b c
+
+\property Staff.SustainPedal \override #'pedal-type = #'bracket
+
+c4 d e \sustainDown b c c, \sustainUp \sustainDown [d8 c] [e8 e \sustainUp \sustainDown] f4 d
+\sustainUp g \sustainDown b b, \sustainUp c'
+
+\property Staff.UnaCordaPedal \override #'pedal-type = #'mixed
+
+c4 d \unaCorda e f g
+ b \treCorde c
+
+
+}
+\paper{
+}
+\midi{
+\tempo 4 = 60
+}
+}
public:
DECLARE_SCHEME_CALLBACK (brew_molecule, (SCM));
static bool has_interface (Grob*);
+private:
+ static void setup_pedal_bracket(Spanner *s);
};
#endif /* TEXT_SPANNER_HH */
Grob *me= unsmob_grob (smob);
Spanner *spanner = dynamic_cast<Spanner*> (me);
+ if (spanner->has_interface (ly_symbol2scm ("piano-pedal-interface")) )
+ {
+ setup_pedal_bracket(spanner);
+ }
/* Ugh, must be same as Hairpin::brew_molecule. */
Drul_array<Molecule> edge_line;
s = me->get_grob_property ("edge-height");
+ SCM ew = me->get_grob_property ("edge-width");
if (gh_pair_p (s))
{
Direction d = LEFT;
int dir = to_dir (me->get_grob_property ("direction"));
do
{
+ Real dx = ( gh_pair_p (ew) ?
+ gh_scm2double (index_cell (ew, d)) * - dir :
+ 0 );
Real dy = gh_scm2double (index_cell (s, d)) * - dir;
if (dy)
{
- SCM list = Line_spanner::line_atom (me, 0, dy);
- Box b (Interval (0, thick),
+ SCM list = Line_spanner::line_atom (me, dx, dy);
+ Box b (Interval (-thick, 0),
dy > 0
? Interval (0, dy)
: Interval (dy, 0));
m.add_at_edge (X_AXIS, RIGHT, edge_line[RIGHT], 0);
if (!edge[RIGHT].empty_b ())
m.add_at_edge (X_AXIS, RIGHT, edge[RIGHT], 0);
- m.translate_axis (broken_left + extra_off[LEFT], X_AXIS);
+ m.translate_axis (broken_left + extra_off[LEFT] + shorten[LEFT], X_AXIS);
return m.smobbed_copy ();
}
+
+/*
+ Piano pedal brackets are a special case of a text spanner.
+ Pedal up-down (restart) indicated by the angled right and left edges
+ of consecutive pedals touching exactly to form an __/\__
+ Chris Jackson <chris@fluffhouse.org.uk>
+
+ TODO: Pedal line extending to the end of the note
+*/
+
+void
+Text_spanner::setup_pedal_bracket(Spanner *s)
+{
+
+ Real thick = s->paper_l ()->get_var ("stafflinethickness");
+ Real ss = Staff_symbol_referencer::staff_space (s);
+
+ Drul_array<bool> a, broken;
+ Drul_array<Real> height, width, shorten, r;
+
+ // Pedal has an angled left edge \__ or an angled right edge __/
+ a[LEFT] = a[RIGHT] = false;
+ SCM al = s->get_grob_property ("angle-left");
+ SCM ar = s->get_grob_property ("angle-right");
+ if (gh_boolean_p (al) )
+ a[LEFT] = to_boolean (al);
+ if (gh_boolean_p (ar) )
+ a[RIGHT] = to_boolean (ar);
+
+ height[LEFT] = ( to_boolean (s->get_grob_property ("text-start")) ?
+ 0 :
+ ss );
+ height[RIGHT] = ss;
+
+ Direction d = LEFT;
+ Interval e;
+ Real padding = 0;
+ SCM pa = (s->get_grob_property ("if-text-padding"));
+ if (gh_number_p (pa) )
+ padding = gh_scm2double (pa);
+ do {
+ Item *b = s->get_bound (d);
+
+ e = b->extent (b, X_AXIS);
+ if (!e.empty_b ())
+ r[d] = d * (e[-d] + padding);
+
+ broken[d] = b->break_status_dir () != CENTER;
+ width[d] = (a[d] ? ss*d/2 : 0);
+ if (broken[d])
+ height[d] = 0;
+ }
+ while (flip (&d) != LEFT);
+
+ shorten[RIGHT] = shorten[LEFT] = 0;
+ Real extra_short = 0;
+ // For 'Mixed' style pedals, i.e. a bracket preceded by text: Ped._____|
+ // need to shorten by the extent of the text grob
+ if ( to_boolean (s->get_grob_property ("text-start")) )
+ {
+ Grob * textbit = s->get_parent(Y_AXIS);
+ extra_short = padding;
+ if (textbit->has_interface(ly_symbol2scm("piano-pedal-interface")))
+ // for pretty Ped. scripts.
+ {
+ e = textbit->extent(textbit, Y_AXIS);
+ extra_short += e.length();
+ }
+ if (textbit->has_interface(ly_symbol2scm("text-interface")))
+ // for plain text, e.g., Sost. Ped.
+ {
+ SCM text = textbit->get_grob_property("text");
+ if (gh_string_p (text)) {
+ SCM properties = Font_interface::font_alist_chain (s);
+ Molecule mol = Text_item::text2molecule (s, text, properties);
+ extra_short += mol.extent(X_AXIS).length() / 2;
+ }
+ }
+ shorten[RIGHT] -= thick;
+ }
+
+ // Shorten a \____ on the left so that it will touch an adjoining ___/
+ shorten[LEFT] += abs(width[LEFT]) * 2 + extra_short ;
+
+ if (broken[LEFT]) {
+ shorten[LEFT] -= s->get_broken_left_end_align () ;
+ shorten[RIGHT] -= r[RIGHT];
+ }
+ else
+ // Shorten bracket on the right so it ends just before the spanned note.
+ shorten[RIGHT] += thick - (r[LEFT] + r[RIGHT]);
+
+ // Hmm. TODO: This should be set in grob-description.scm, but side-positioning
+ // of consecutive brackets only seems to work if direction is +1 within the engraver.
+ s->set_grob_property ("direction", gh_int2scm(-1));
+
+ s->set_grob_property ("edge-height", gh_cons ( gh_double2scm ( height[LEFT] ) ,
+ gh_double2scm ( height[RIGHT]) ) );
+ s->set_grob_property ("edge-width", gh_cons ( gh_double2scm ( width[LEFT] ),
+ gh_double2scm ( width[RIGHT] ) ));
+ s->set_grob_property ("shorten", gh_cons ( gh_double2scm ( shorten[LEFT] ),
+ gh_double2scm ( shorten[RIGHT] ) ));
+}
;; in principle, have one or more uppercase letters
"\\(\\(BarNumbering\\|Choir\\|Grand\\|HaraKiri\\|OrchestralPart\\|Piano\\|Rhythmic\\)Staff\\|\\(Cue\\|Lyrics\\)?Voice\\|\\(Orchestral\\)?Score\\|ChordNames\\|Grace\\|Lyrics\\|StaffGroup\\|Thread\\)Context" ; *Context
-"\\(script\\|dots\\|dynamic\\|slur\\|stem\\|sustain\\|tie\\|tuplet\\)\\(Both\\|Down\\|Up\\)" ; *(Both/Down/Up)
+"\\(script\\|dots\\|dynamic\\|slur\\|stem\\|sustain\\|sostenuto\\|unaCorda\\|treCorde\\|tie\\|tuplet\\)\\(Both\\|Down\\|Up\\)" ; *(Both/Down/Up)
"\\(slur\\|tie\\)\\(Dotted\\|Solid\\)" ; *(Dotted/Solid)
"\\(autoBeam\\|cadenza\\|impro\\|turn\\)\\(Off\\|On\\)" ; *(On/Off)
"\\(empty\\|fat\\)Text" ; *Text
pedalSustainStrings = #'("Ped." "*Ped." "*")
pedalUnaCordaStrings = #'("una corda" "" "tre corde")
- pedalSostenutoStrings = #'() % FIXME
+
+ %% these are in ordinary italic font, including the *, but they are unlikely to be used,
+ %% as the default pedal-style for SostenutoPedal is 'mixed': i.e. Sost. Ped_____________________
+ pedalSostenutoStrings = #'("Sost. Ped." "*Sost. Ped." "*")
tupletNumberFormatFunction = #denominator-tuplet-formatter
. (
;; todo: clean this up a bit: the list is getting
;; rather long.
- ;(molecule-callback . ,Beam::brew_molecule)
- (molecule-callback . ,New_beam::brew_molecule)
+ (molecule-callback . ,Beam::brew_molecule)
(concaveness-threshold . 0.08)
- (position . (#f . #f))
- (y-dy-callbacks . (,Beam::least_squares
- ,Beam::check_concave
- ,Beam::slope_damping
- ,Beam::quantise_dy
- ,Beam::user_override
- ,Beam::do_quantise_y))
-
- (position-callbacks . (,New_beam::least_squares
- ,New_beam::check_concave
- ,New_beam::slope_damping
- ,New_beam::quantise_position))
+ (positions . (#f . #f))
+ (position-callbacks . (,Beam::least_squares
+ ,Beam::check_concave
+ ,Beam::slope_damping
+ ,Beam::quantise_position))
(thickness . 0.48) ; in staff-space
(before-line-breaking-callback . ,Beam::before_line_breaking)
- ;;(after-line-breaking-callback . ,Beam::after_line_breaking)
- (after-line-breaking-callback . (,New_beam::after_line_breaking
- ,New_beam::end_after_line_breaking))
+ (after-line-breaking-callback . (,Beam::after_line_breaking
+ ,Beam::end_after_line_breaking))
(neutral-direction . -1)
(dir-function . ,beam-dir-majority)
- (height-quant-function . ,default-beam-dy-quants)
- (vertical-position-quant-function . ,default-beam-y-quants)
+ (vertical-position-quant-function . ,default-beam-pos-quants)
(beamed-stem-shorten . (1.0 0.5))
(outer-stem-length-limit . 0.2)
(slope-limit . 0.2)
(meta . ,(grob-description multi-measure-rest-interface font-interface percent-repeat-interface))
))
+ (PianoPedalBracket ;; an example of a text spanner
+ . (
+ (molecule-callback . ,Text_spanner::brew_molecule)
+ (font-family . roman)
+ (type . line)
+ (if-text-padding . 1.0)
+ (width-correct . 0)
+ (outer . #t)
+ (angle-left . #f)
+ (angle-right . #f)
+ (text-start . #f)
+ (meta . ,(grob-description text-spanner-interface piano-pedal-interface font-interface))
+ ))
+
(RepeatSlash
. (
(molecule-callback . , Percent_repeat_item_interface::beat_slash)
(SostenutoPedal
. (
(molecule-callback . ,Text_item::brew_molecule)
- (direction . -1)
+ (direction . 1)
(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
- (Y-offset-callbacks .
- (,Side_position_interface::aligned_side
- ,Side_position_interface::centered_on_parent))
+ (Y-offset-callbacks . (,Side_position_interface::aligned_side))
(no-spacing-rods . #t)
+ (padding . 0.0) ;; padding relative to SostenutoPedalLineSpanner
+ (pedal-type . mixed)
+ (font-family . roman)
(font-shape . italic)
(self-alignment-X . 0)
(meta . ,(grob-description text-interface font-interface))
))
+ (SostenutoPedalLineSpanner
+ . (
+ (axes . ( 1))
+ (padding . 1.2)
+ (minimum-space . 1.0)
+ (direction . -1)
+ (meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
+ ))
+
(Stem
. (
(before-line-breaking-callback . ,Stem::before_line_breaking)
(no-spacing-rods . #t)
(molecule-callback . ,Sustain_pedal::brew_molecule)
(self-alignment-X . 0)
- (direction . -1)
+ (direction . 1)
+ (padding . 0.0) ;; padding relative to SustainPedalLineSpanner
+ (pedal-type . text)
(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
- (Y-offset-callbacks .
- (,Side_position_interface::aligned_side
- ,Side_position_interface::centered_on_parent))
+ (Y-offset-callbacks . (,Side_position_interface::aligned_side ))
+ (meta . ,(grob-description piano-pedal-interface side-position-interface font-interface))
+ ))
- (meta . ,(grob-description sustain-pedal-interface side-position-interface font-interface))
+ (SustainPedalLineSpanner
+ . (
+ (axes . ( 1))
+ (padding . 1.2)
+ (minimum-space . 1.0)
+ (direction . -1)
+ (meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
))
(SystemStartBrace
. (
(molecule-callback . ,Text_spanner::brew_molecule)
(font-family . roman)
- (type . "line")
+ (type . line)
;; urg, only for (de)cresc. text spanners
(if-text-padding . 1.0)
(font-shape . italic)
(no-spacing-rods . #t)
(self-alignment-X . 0)
- (direction . -1)
+ (direction . 1)
+ (pedal-type . text)
+ (padding . 0.0) ;; padding relative to UnaCordaPedalLineSpanner
(X-offset-callbacks . (,Side_position_interface::aligned_on_self))
- (Y-offset-callbacks .
- (,Side_position_interface::aligned_side
- ,Side_position_interface::centered_on_parent))
+ (Y-offset-callbacks . (,Side_position_interface::aligned_side ))
(meta . ,(grob-description text-interface font-interface))
))
+ (UnaCordaPedalLineSpanner
+ . (
+ (axes . ( 1))
+ (padding . 1.2)
+ (minimum-space . 1.0)
+ (direction . -1)
+ (meta . ,(grob-description piano-pedal-interface axis-group-interface side-position-interface))
+ ))
+
(VoltaBracket
. (
(molecule-callback . ,Volta_spanner::brew_molecule)
contains-grace extra-space stretch-distance ))
+ (lily-interface
+ 'piano-pedal-interface
+ ""
+ '(pedal-type
+ ))
+
(lily-interface
'porrectus-interface
))
- (lily-interface
- 'sustain-pedal-interface
- ""
- '(
- ))
-
(lily-interface
'system-start-delimiter-interface
"#'style can be bar-line, bracket or brace"
dash-length
line-thickness
edge-height
+ edge-width
edge-text
type
))
(define (dashed-line thick on off dx dy)
(string-append
- (ly-number->string dx)
+ (ly-number->string (* dx (/ 72 72.27)))
" "
(ly-number->string dy)
" "
- (ly-number->string thick)
+ (ly-number->string (* thick (/ 72 72.27)))
" [ "
(ly-number->string on)
" "