From 023b049d582ac738ba8486409545df7369d98f6f Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Mon, 4 Mar 2002 11:19:54 +0100 Subject: [PATCH] release: 1.4.12 ========== * 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. --- CHANGES | 9 ++ Documentation/user/refman.itely | 29 +++++- VERSION | 2 +- input/regression/rest-pitch.ly | 16 ++++ lily/lexer.ll | 2 + lily/music-list.cc | 28 ++++-- lily/my-lily-lexer.cc | 1 + lily/note-column.cc | 7 +- lily/parser.yy | 29 +++++- lily/piano-pedal-performer.cc | 2 +- lily/rest-engraver.cc | 25 ++++- lily/span-bar.cc | 11 ++- lily/staff-symbol-referencer.cc | 6 +- make/out/lilypond.lsm | 8 +- make/out/lilypond.redhat.spec | 4 +- make/out/lilypond.suse.spec | 4 +- scm/c++.scm | 8 +- scm/music-functions.scm | 164 ++++++++++++++++++++++++++++++++ 18 files changed, 311 insertions(+), 44 deletions(-) create mode 100644 input/regression/rest-pitch.ly diff --git a/CHANGES b/CHANGES index 41a91106ab..93fe8e0efd 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +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 ========== diff --git a/Documentation/user/refman.itely b/Documentation/user/refman.itely index c1ba7b0148..c49f6c1c0c 100644 --- a/Documentation/user/refman.itely +++ b/Documentation/user/refman.itely @@ -229,6 +229,14 @@ catalan.ly do re mi fa sol la sib si -d/-s -b @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 @@ -831,8 +839,25 @@ a measure it is set to @code{defaultBarType}. The contents of @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' } diff --git a/VERSION b/VERSION index 56f2ec2691..cad6ec9f68 100644 --- a/VERSION +++ b/VERSION @@ -1,7 +1,7 @@ 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 diff --git a/input/regression/rest-pitch.ly b/input/regression/rest-pitch.ly new file mode 100644 index 0000000000..e864dade12 --- /dev/null +++ b/input/regression/rest-pitch.ly @@ -0,0 +1,16 @@ +\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 + + + +} +} diff --git a/lily/lexer.ll b/lily/lexer.ll index a875cea59e..ea40d1d8ca 100644 --- a/lily/lexer.ll +++ b/lily/lexer.ll @@ -444,6 +444,8 @@ HYPHEN -- return E_SMALLER; case '!': return E_EXCLAMATION; + case '\\': + return E_BACKSLASH; case '(': return E_OPEN; case ')': diff --git a/lily/music-list.cc b/lily/music-list.cc index 5870ae3ec2..90a11d1844 100644 --- a/lily/music-list.cc +++ b/lily/music-list.cc @@ -82,15 +82,25 @@ Request_chord::to_relative_octave (Pitch last) 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 (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 (mus); + + /* + kLudge: rests have pitches now as well. + */ + Rest_req *r = dynamic_cast (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; } diff --git a/lily/my-lily-lexer.cc b/lily/my-lily-lexer.cc index 3190df807f..29ca02670e 100644 --- a/lily/my-lily-lexer.cc +++ b/lily/my-lily-lexer.cc @@ -69,6 +69,7 @@ static Keyword_ent the_key_tab[]={ {"outputproperty", OUTPUTPROPERTY}, {"override", OVERRIDE}, {"set", SET}, + {"rest", REST}, {"revert", REVERT}, {"partial", PARTIAL}, {"paper", PAPER}, diff --git a/lily/note-column.cc b/lily/note-column.cc index 6cf77b6d5e..84a070427f 100644 --- a/lily/note-column.cc +++ b/lily/note-column.cc @@ -106,13 +106,14 @@ Note_column::add_head (Grob*me,Grob *h) } /** - 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); } diff --git a/lily/parser.yy b/lily/parser.yy index 0f92f6c5f2..4803c2eae5 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -231,12 +231,14 @@ yylex (YYSTYPE *s, void * v_l) %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 exclamations questions dots +%type exclamations questions dots optional_rest %token DIGIT %token NOTENAME_PITCH %token TONICNAME_PITCH @@ -1066,6 +1068,16 @@ command_element: $$-> 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 (); @@ -1640,18 +1652,29 @@ tremolo_type: ; + +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) diff --git a/lily/piano-pedal-performer.cc b/lily/piano-pedal-performer.cc index aa8ee6196c..41e4a4a4d9 100644 --- a/lily/piano-pedal-performer.cc +++ b/lily/piano-pedal-performer.cc @@ -59,7 +59,7 @@ Piano_pedal_performer::initialize () 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 { diff --git a/lily/rest-engraver.cc b/lily/rest-engraver.cc index 702b98b5aa..93c43adfdf 100644 --- a/lily/rest-engraver.cc +++ b/lily/rest-engraver.cc @@ -22,10 +22,9 @@ protected: 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 (); }; @@ -63,13 +62,13 @@ Rest_engraver::stop_translation_timestep () } 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 (); @@ -88,6 +87,24 @@ Rest_engraver::create_grobs () 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_); } } diff --git a/lily/span-bar.cc b/lily/span-bar.cc index 3597e6018d..89ebf63f6a 100644 --- a/lily/span-bar.cc +++ b/lily/span-bar.cc @@ -92,10 +92,13 @@ Span_bar::brew_molecule (SCM smobbed_me) 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; } diff --git a/lily/staff-symbol-referencer.cc b/lily/staff-symbol-referencer.cc index 13cf324351..cb22f57792 100644 --- a/lily/staff-symbol-referencer.cc +++ b/lily/staff-symbol-referencer.cc @@ -99,10 +99,9 @@ Staff_symbol_referencer::callback (SCM element_smob, SCM) { 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); } @@ -164,9 +163,6 @@ compare_position (Grob *const &a, Grob * const &b) 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); } diff --git a/make/out/lilypond.lsm b/make/out/lilypond.lsm index dfd1c5ab50..5df075e20e 100644 --- a/make/out/lilypond.lsm +++ b/make/out/lilypond.lsm @@ -1,15 +1,15 @@ 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 diff --git a/make/out/lilypond.redhat.spec b/make/out/lilypond.redhat.spec index 75b77053d0..ee8cd7c287 100644 --- a/make/out/lilypond.redhat.spec +++ b/make/out/lilypond.redhat.spec @@ -1,11 +1,11 @@ %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 diff --git a/make/out/lilypond.suse.spec b/make/out/lilypond.suse.spec index 32318f452e..d900a53ee3 100644 --- a/make/out/lilypond.suse.spec +++ b/make/out/lilypond.suse.spec @@ -14,11 +14,11 @@ 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/ diff --git a/scm/c++.scm b/scm/c++.scm index 852def1a07..5472f7b0cf 100644 --- a/scm/c++.scm +++ b/scm/c++.scm @@ -88,10 +88,10 @@ (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))))) diff --git a/scm/music-functions.scm b/scm/music-functions.scm index b708b44768..f5cc961493 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -8,3 +8,167 @@ (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) + + ) + )) + -- 2.39.5