+1.4.11.uu1
+==========
+
+* Backport from 1.5: pitched rest. Syntax a4\rest
+
+* Backport from 1.5: on-the-fly polyphony. See reference manual.
+
+* Backport from 1.5: bugfix with overlapping bars and span-bars.
+
1.4.10.uu1
==========
@cindex @code{,}
+For polyphonic music, it can be convenient to specify the rest position
+directly. You can do that by entering a note, with the keyword
+@code{\rest} appended, e.g. Rest collisions will leave these rests alone.
+
+@lilypond[singleline,verbatim]
+a'4\rest d'4\rest
+@end lilypond
+
The optional octave specification takes the form of a series of
single quote (`@code{'}') characters or a series of comma
@cindex polyphony
Polyphonic parts, i.e. parts with more than one voice on a staff can be
-typeset with LilyPond. To use this, instantiate a separate Voice
-context for each part, and assign a stem direction to each part.
+typeset with LilyPond.
+
+The easiest way to enter such fragments, is the Scheme function
+@code{voicify-music}. It will split chords using the separator
+@code{\\}, to make multiple voices. You can use it for small,
+short-lived voices (make a chord of voices) or for single chords:
+
+@lilypond[verbatim,fragment]
+\context Voice = VA \apply #voicify-music \relative c'' {
+ c4 < { f d e } \\ { b c2 } > c4 < g' \\ c, \\ f \\ d >
+}
+@end lilypond
+
+The function @code{voicify-music} instantiates @internalsref{Voice}
+contexts, bearing the names @code{"1"}, @code{"2"}, etc.
+
+To explicity typeset polyphonic music, instantiate a separate Voice
+context for each part, and assign a stem direction to each part.
+@c
@lilypond[fragment,verbatim]
\context Staff
< \context Voice = VA { \stemUp b'4 a' g' f' e' }
PACKAGE_NAME=LilyPond
MAJOR_VERSION=1
MINOR_VERSION=4
-PATCH_LEVEL=11
+PATCH_LEVEL=12
MY_PATCH_LEVEL=
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
--- /dev/null
+\header {
+
+texidoc = "Rests can have pitches--these will be affected by
+transposition and relativization. If a rest has a pitch, rest
+collision will leave it alone."
+
+}
+
+\score { \notes\relative c'' \apply #voicify-music
+{
+ a4\rest b4\rest c4\rest
+
+<d \\ d\rest^"rest pitch" >
+<d \\ r>
+}
+}
return E_SMALLER;
case '!':
return E_EXCLAMATION;
+ case '\\':
+ return E_BACKSLASH;
case '(':
return E_OPEN;
case ')':
for (SCM s = music_list (); gh_pair_p (s); s = gh_cdr (s))
{
Music * mus = unsmob_music (gh_car (s));
- if (Melodic_req *m= dynamic_cast <Melodic_req *> (mus))
- {
- Pitch pit = *unsmob_pitch (m->get_mus_property ("pitch"));
-
- pit.to_relative_octave (last);
- m->set_mus_property ("pitch", pit.smobbed_copy ());
-
- return pit;
- }
+ Melodic_req *m= dynamic_cast <Melodic_req *> (mus);
+
+ /*
+ kLudge: rests have pitches now as well.
+ */
+ Rest_req *r = dynamic_cast<Rest_req*> (mus);
+
+ if (r || m)
+ {
+ Pitch *old_pit = unsmob_pitch (mus->get_mus_property ("pitch"));
+ if (!old_pit)
+ continue;
+
+ Pitch new_pit = *old_pit;
+ new_pit.to_relative_octave (last);
+ mus->set_mus_property ("pitch", new_pit.smobbed_copy ());
+
+ return new_pit;
+ }
}
return last;
}
{"outputproperty", OUTPUTPROPERTY},
{"override", OVERRIDE},
{"set", SET},
+ {"rest", REST},
{"revert", REVERT},
{"partial", PARTIAL},
{"paper", PAPER},
}
/**
- translate the rest symbols vertically by amount DY_I.
- */
+ translate the rest symbols vertically by amount DY_I, but only if
+ they have no staff-position set.
+*/
void
Note_column::translate_rests (Grob*me,int dy_i)
{
Grob * r = unsmob_grob (me->get_grob_property ("rest"));
- if (r)
+ if (r && !gh_number_p (r->get_grob_property ("staff-position")))
{
r->translate_axis (dy_i * Staff_symbol_referencer::staff_space (r)/2.0, Y_AXIS);
}
%token TYPE
%token UNSET
%token CONTEXT
+%token REST
/* escaped */
%token E_CHAR E_EXCLAMATION E_SMALLER E_BIGGER E_OPEN E_CLOSE
+%token E_BACKSLASH
%token CHORD_BASS CHORD_COLON CHORD_MINUS CHORD_CARET
-%type <i> exclamations questions dots
+%type <i> exclamations questions dots optional_rest
%token <i> DIGIT
%token <scm> NOTENAME_PITCH
%token <scm> TONICNAME_PITCH
$$-> set_spot (THIS->here_input ());
$1-> set_spot (THIS->here_input ());
}
+ | E_BACKSLASH {
+ $$ = new Music (gh_list (gh_cons (ly_symbol2scm ("name"), ly_symbol2scm ("separator")), SCM_UNDEFINED));
+ $$->set_spot (THIS->here_input ());
+ }
+ | '|' {
+
+ extern Music * get_barcheck();
+ $$ = get_barcheck ();
+ $$->set_spot (THIS->here_input ());
+ }
| '|' {
extern Music * get_barcheck();
$$ = get_barcheck ();
;
+
+optional_rest:
+ /**/ { $$ = 0; }
+ | REST { $$ = 1; }
+ ;
+
simple_element:
- pitch exclamations questions optional_notemode_duration {
+ pitch exclamations questions optional_notemode_duration optional_rest {
Input i = THIS->pop_spot ();
if (!THIS->lexer_p_->note_state_b ())
THIS->parser_error (_ ("Have to be in Note mode for notes"));
- Note_req *n = new Note_req;
+ Music *n = 0;
+ if ($5)
+ n = new Rest_req ;
+ else
+ n = new Note_req;
n->set_mus_property ("pitch", $1);
n->set_mus_property ("duration", $4);
+
if ($3 % 2)
n->set_mus_property ("cautionary", SCM_BOOL_T);
if ($2 % 2 || $3 % 2)
info_alist_ = new Pedal_info[4];
Pedal_info *p = info_alist_;
- char * names [] = { "Sostenuto", "Sustain", "UnaChorda", 0 };
+ char * names [] = { "Sostenuto", "Sustain", "UnaCorda", 0 };
char **np = names ;
do
{
virtual bool try_music (Music *);
virtual void stop_translation_timestep ();
virtual void start_translation_timestep ();
- virtual void create_grobs ();
+ virtual void process_music ();
public:
-
VIRTUAL_COPY_CONS (Translator);
Rest_engraver ();
};
}
void
-Rest_engraver::create_grobs ()
+Rest_engraver::process_music ()
{
if (rest_req_l_ && !rest_p_)
{
rest_p_ = new Item (get_property ("Rest"));
Rhythmic_head::set_interface (rest_p_);
- Staff_symbol_referencer::set_interface (rest_p_);
+
int durlog = unsmob_duration (rest_req_l_->get_mus_property ("duration"))-> duration_log ();
announce_grob (dot_p_,0);
}
+
+ Pitch *p = unsmob_pitch (rest_req_l_->get_mus_property ("pitch"));
+
+ /*
+ This is ridiculous -- rests don't have pitch, but we act as if
+ our nose is bleeding.
+ */
+ if (p)
+ {
+ int pos= p->steps ();
+ SCM c0 = get_property ("centralCPosition");
+ if (gh_number_p (c0))
+ pos += gh_scm2int (c0);
+
+ rest_p_->set_grob_property ("staff-position", gh_int2scm (pos));
+ }
+
+
announce_grob (rest_p_, rest_req_l_);
}
}
Interval l(prev_extent [UP],
ext[DOWN]);
- Molecule interbar
- = Bar::compound_barline (staff_bar, glyph_str, l.length());
- interbar.translate_axis (l.center (), Y_AXIS);
- span_bar_mol.add_molecule (interbar);
+ if (!l.empty_b ())
+ {
+ Molecule interbar
+ = Bar::compound_barline (staff_bar, glyph_str, l.length());
+ interbar.translate_axis (l.center (), Y_AXIS);
+ span_bar_mol.add_molecule (interbar);
+ }
}
prev_extent = ext;
}
{
Real space = Staff_symbol_referencer::staff_space (me);
off = gh_scm2double (pos) * space/2.0;
+ me->set_grob_property ("staff-position", gh_double2scm (0.0));
}
- me->set_grob_property ("staff-position", gh_double2scm (0.0));
-
return gh_double2scm (off);
}
void
Staff_symbol_referencer::set_interface (Grob * e)
{
- if (!gh_number_p (e->get_grob_property ("staff-position")))
- e->set_grob_property ("staff-position", gh_double2scm (0.0));
-
e->add_offset_callback (Staff_symbol_referencer::callback_proc, Y_AXIS);
}
Begin3
Title: LilyPond
-Version: 1.4.11
-Entered-date: 22FEB02
+Version: 1.4.12
+Entered-date: 04MRT02
Description: @BLURB@
Keywords: music notation typesetting midi fonts engraving
Author: hanwen@cs.uu.nl (Han-Wen Nienhuys)
janneke@gnu.org (Jan Nieuwenhuizen)
Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys)
Primary-site: sunsite.unc.edu /pub/Linux/apps/sound/convert
- 1000k lilypond-1.4.11.tar.gz
+ 1000k lilypond-1.4.12.tar.gz
Original-site: ftp.cs.uu.nl /pub/GNU/LilyPond/development/
- 1000k lilypond-1.4.11.tar.gz
+ 1000k lilypond-1.4.12.tar.gz
Copying-policy: GPL
End
%define info yes
Name: lilypond
-Version: 1.4.11
+Version: 1.4.12
Release: 1
License: GPL
Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.4.11.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.4.12.tar.gz
Summary: Create and print music notation
URL: http://www.cs.uu.nl/~hanwen/lilypond
BuildRoot: /tmp/lilypond-install
Distribution: SuSE Linux 7.0 (i386)
Name: lilypond
-Version: 1.4.11
+Version: 1.4.12
Release: 2
Copyright: GPL
Group: Applications/Publishing
-Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.4.11.tar.gz
+Source0: ftp.cs.uu.nl:/pub/GNU/LilyPond/development/lilypond-1.4.12.tar.gz
# music notation software for.. ?
Summary: A program for printing sheet music.
URL: http://www.lilypond.org/
(define (cons-map f x)
(cons (f (car x)) (f (cdr x))))
-;; used where?
-;;(define (reduce operator list)
-;; (if (null? (cdr list)) (car list)
-;; (operator (car list) (reduce operator (cdr list)))))
+
+(define (reduce operator list)
+ (if (null? (cdr list)) (car list)
+ (operator (car list) (reduce operator (cdr list)))))
(number->string (ly-get-mus-property mus 'denominator))
))
+
+(define (make-grob-property-set grob gprop val)
+ "Make a M-exp that sets GPROP to VAL in GROBS. Does a pop first, i.e.
+this is not an override
+"
+
+ (let* ((m (ly-make-music "Music")))
+ (ly-set-mus-property m 'iterator-ctor Push_property_iterator::constructor)
+ (ly-set-mus-property m 'symbols grob)
+ (ly-set-mus-property m 'grob-property gprop)
+ (ly-set-mus-property m 'grob-value val)
+ (ly-set-mus-property m 'pop-first #t)
+
+ m
+
+ ))
+
+(define (make-grob-property-revert grob gprop)
+ "Revert the grob property GPROP for GROB."
+ (let* ((m (ly-make-music "Music")))
+ (ly-set-mus-property m 'iterator-ctor Pop_property_iterator::constructor)
+ (ly-set-mus-property m 'symbols grob)
+ (ly-set-mus-property m 'grob-property gprop)
+
+ m
+
+ ))
+
+(define (make-voice-props-set n)
+ (make-sequential-music
+ (append
+ (map (lambda (x) (make-grob-property-set x 'direction
+ (if (odd? n) -1 1)))
+ '(Tie Slur Stem Dots))
+ (list (make-grob-property-set 'NoteColumn 'horizontal-shift (quotient n 2)))
+ )
+ ))
+
+(define (make-voice-props-revert)
+ (make-sequential-music
+ (list
+ (make-grob-property-revert 'Tie 'direction)
+ (make-grob-property-revert 'Dots 'direction)
+ (make-grob-property-revert 'Stem 'direction)
+ (make-grob-property-revert 'Slur 'direction)
+ (make-grob-property-revert 'NoteColumn 'horizontal-shift)
+ ))
+ )
+
+(define (context-spec-music m context . rest)
+ "Add \context CONTEXT = foo to M. "
+
+ (let* ((cm (ly-make-music "Context_specced_music")))
+ (ly-set-mus-property cm 'element m)
+ (ly-set-mus-property cm 'context-type context)
+ (if (and (pair? rest) (string? (car rest)))
+ (ly-set-mus-property cm 'context-id (car rest))
+ )
+ cm
+ ))
+
+
+
+(define (make-sequential-music elts)
+ (let* ((m (ly-make-music "Sequential_music")))
+ (ly-set-mus-property m 'elements elts)
+ m
+ ))
+(define (make-simultaneous-music elts)
+ (let* ((m (ly-make-music "Simultaneous_music")))
+ (ly-set-mus-property m 'elements elts)
+ m
+ ))
+(define (music-separator? m)
+ "Is M a separator."
+ (let* ((n (ly-get-mus-property m 'name )))
+ (and (symbol? n) (equal? 'separator n))
+ ))
+
+
+(define (split-one sep? l acc)
+ "Split off the first parts before separator and return both parts.
+
+"
+ (if (null? l)
+ (cons acc '())
+ (if (sep? (car l))
+ (cons acc (cdr l))
+ (split-one sep? (cdr l) (cons (car l) acc))
+ )
+ ))
+
+(define (split-list l sep?)
+ (if (null? l)
+ '()
+ (let* ((c (split-one sep? l '())))
+ (cons (reverse! (car c) '()) (split-list (cdr c) sep?))
+ )
+ )
+ )
+
+;; test code
+; (display (split-list '(a b c / d e f / g) (lambda (x) (equal? x '/))) )
+
+
+
+;;; splitting chords into voices.
+
+(define (voicify-list lst number)
+ "Make a list of Musics.
+
+ voicify-list :: [ [Music ] ] -> number -> [Music]
+ LST is a list music-lists.
+"
+
+ (if (null? lst) '()
+ (cons (context-spec-music
+ (make-sequential-music
+ (list
+ (make-voice-props-set number)
+ (make-simultaneous-music (car lst))))
+
+ "Voice" (number->string number))
+ (voicify-list (cdr lst) (+ number 1))
+ ))
+ )
+
+(define (voicify-chord ch)
+ "Split the parts of a chord into different Voices using separator"
+ (let* ((es (ly-get-mus-property ch 'elements)))
+
+
+ (ly-set-mus-property ch 'elements
+ (voicify-list (split-list es music-separator?) 0))
+ ch
+ ))
+
+(define (voicify-music m)
+ "Recursively split chords that are separated with \\ "
+
+ (if (not (music? m))
+ (begin (display m)
+ (error "not music!"))
+ )
+ (let*
+ ((es (ly-get-mus-property m 'elements))
+ (e (ly-get-mus-property m 'element))
+ )
+
+ (if
+ (and (equal? (ly-music-name m) "Simultaneous_music")
+ (reduce (lambda (x y ) (or x y)) (map music-separator? es)))
+ (voicify-chord m)
+ (begin
+ (if (pair? es)
+ (ly-set-mus-property m 'elements (map voicify-music es)))
+ (if (music? e)
+ (ly-set-mus-property m 'element (voicify-music e)))
+
+ m)
+
+ )
+ ))
+