+2004-02-03 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * scm/music-functions.scm (determine-split-list): further analysis.
+
+ * lily/script-engraver.cc (try_music): discard duplicate
+ articulations.
+
+ * input/regression/new-part-combine-solo.ly: new file
+
+ * input/regression/new-part-combine-a2.ly: new file.
+
+ * ly/performer-init.ly: add Devnull
+
+ * scripts/convert-ly.py (FatalConversionError.sub_acc): add rule
+ for \musicglyph #"accidental-*"
+ (conv): \newpartcombine rule.
+
2004-02-03 Jan Nieuwenhuizen <janneke@gnu.org>
* scripts/filter-lilypond-book.py: Handle @lilypondfile, bugfixes.
2004-02-02 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * scm/new-markup.scm (doubleflat): add accidental markups.
+
* VERSION: release 2.1.17
* Documentation/user/refman.itely (Automatic part combining):
MAJOR_VERSION=2
MINOR_VERSION=1
PATCH_LEVEL=17
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=hwn1
--- /dev/null
+
+\header {
+ texidoc ="The a2 string is only printed on notes, not on rests,
+and only after chords, solo or polyphony."
+ }
+
+vone = \notes \relative a' { R1*2 g2 r2 g2 r2 a4 r4 g
+ }
+vtwo = \notes \relative a' { R1*2 g2 r2 g2 r2 f4 r4 g }
+
+\score {
+ << \property Score.skipBars = ##t
+ \newpartcombine \vone \vtwo
+ >>
+}
+
--- /dev/null
+
+\header { texidoc =
+
+ "A solo string can only be printed when a note
+ starts. Hence, in this example, there is no Solo-2 although the
+ 2nd voice has a dotted quarter, while the first voice has a rest.
+
+A Solo indication is only printed once; (shared) rests do not require
+reprinting a solo indication.
+
+"
+ }
+
+vone = \notes \relative a' { g4 r8 g8 g8 r8 g8 r8 }
+vtwo = \notes \relative g' { e4. e8 r2 }
+
+\score {
+ << \property Score.skipBars = ##t
+ \newpartcombine \vone \vtwo
+ >>
+}
+
texidoc ="The new part combiner:
Detect a2, solo1, solo2 and print texts accordingly.
+
"
}
-vone = \notes \relative a' { R1 a4 r4 r r a a a a }
+vone = \notes \relative a' { R1 a2 r4 r a a a a }
vtwo = \notes \relative a' { R1 f4 f4 f4 f f f a a }
\score {
/*
- new-part-combine-music-iterator.cc -- implement New_pc_iterator
+ new-part-combine-music-iterator.cc -- implement New_pc_iterator
- source file of the GNU LilyPond music typesetter
+ source file of the GNU LilyPond music typesetter
- (c) 2004 Han-Wen Nienhuys
- */
+ (c) 2004 Han-Wen Nienhuys
+*/
#include "part-combine-music-iterator.hh"
#include "translator-group.hh"
private:
Music_iterator * first_iter_;
Music_iterator * second_iter_;
- bool is_shared_ ;
+
SCM split_list_;
- enum {
+ enum Status {
APART, TOGETHER,
SOLO1, SOLO2,
- UNISONO,
- } state_;
+ UNISONO, UNISILENCE,
+ };
+ Status state_;
+ Status playing_state_;
Interpretation_context_handle one_;
Interpretation_context_handle two_;
Interpretation_context_handle shared_;
void chords_together ();
- void apart ();
void solo1 ();
void solo2 ();
- void unisono ();
+ void apart (bool silent);
+ void unisono (bool silent);
};
New_pc_iterator::New_pc_iterator ()
{
- is_shared_ =false;
first_iter_ = 0;
second_iter_ = 0;
split_list_ = SCM_EOL;
state_ = APART;
+ playing_state_ = APART;
}
void
return;
else
{
+ playing_state_ = TOGETHER;
state_ = TOGETHER;
first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
- static Music* event;
- if (!event)
- event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
+ if (playing_state_ != SOLO1)
+ {
+ static Music* event;
+ if (!event)
+ event = make_music_by_name (ly_symbol2scm ("SoloOneEvent"));
- first_iter_-> try_music_in_children (event);
+ first_iter_-> try_music_in_children (event);
+ }
+ playing_state_ = SOLO1;
}
}
void
-New_pc_iterator::unisono ()
+New_pc_iterator::unisono (bool silent)
{
- if (state_ == UNISONO)
- return;
+ Status newstate = (silent) ? UNISILENCE : UNISONO;
+
+ if (newstate == state_)
+ return;
else
{
- state_ = UNISONO;
first_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
first_iter_->substitute_outlet (one_.report_to (), shared_.report_to ());
second_iter_->substitute_outlet (two_.report_to (), null_.report_to ());
second_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
+ if (playing_state_ != UNISONO
+ && newstate == UNISONO)
+ {
+ static Music* event;
+ if (!event)
+ event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
- static Music* event;
- if (!event)
- event = make_music_by_name (ly_symbol2scm ("UnisonoEvent"));
-
- first_iter_-> try_music_in_children (event);
+ first_iter_-> try_music_in_children (event);
+ playing_state_ = UNISONO;
+ }
+ state_ = newstate;
}
}
else
{
state_ = SOLO2;
+
second_iter_->substitute_outlet (null_.report_to (), shared_.report_to ());
second_iter_->substitute_outlet (two_.report_to (), shared_.report_to ());
first_iter_->substitute_outlet (one_.report_to (), null_.report_to ());
first_iter_->substitute_outlet (shared_.report_to (), null_.report_to ());
- static Music* event;
- if (!event)
- event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
+ if (playing_state_ != SOLO2)
+ {
+ static Music* event;
+ if (!event)
+ event = make_music_by_name (ly_symbol2scm ("SoloTwoEvent"));
- second_iter_-> try_music_in_children (event);
+ second_iter_-> try_music_in_children (event);
+ playing_state_ = SOLO2;
+ }
}
}
void
-New_pc_iterator::apart ()
+New_pc_iterator::apart (bool silent)
{
+ if (!silent)
+ playing_state_ = APART;
+
if (state_ == APART)
return;
else
Translator_group *null
= report_to ()->find_create_translator (ly_symbol2scm ("Devnull"),
"", SCM_EOL);
+
+ if (!null)
+ programming_error ("No Devnull found?");
+
null_.set_translator (null);
Translator_group *one = tr->find_create_translator (ly_symbol2scm ("Voice"),
if (tag == ly_symbol2scm ("chords"))
chords_together ();
- else if (tag == ly_symbol2scm ("apart"))
- apart ();
+ else if (tag == ly_symbol2scm ("apart")
+ || tag == ly_symbol2scm ("apart-silence"))
+ apart (tag == ly_symbol2scm ("apart-silence"));
else if (tag == ly_symbol2scm ("unisono"))
- unisono ();
+ unisono (false);
+ else if (tag == ly_symbol2scm ("unisilence"))
+ unisono (true);
else if (tag == ly_symbol2scm ("solo1"))
solo1 ();
else if (tag == ly_symbol2scm ("solo2"))
{
if (r->is_mus_type ("articulation-event"))
{
+ /*
+ Discard double articulations.
+ This is necessary for part-combining.
+ */
+ for (int j = 0; j < scripts_.size (); j++)
+ if (gh_equal_p (scripts_[j]. event_->get_mus_property ("articulation-type"),
+ r->get_mus_property ("articulation-type")
+ ))
+ return true;
+
Script_tuple t;
t.event_ =r;
scripts_.push (t);
+
return true;
}
return false;
\consists "Swallow_performer"
}
+\translator {
+ \type "Performer_group_performer"
+ \name "Devnull"
+ \consists "Swallow_performer"
+}
\translator {
\type "Performer_group_performer"
\name "TabStaff"
(Y-offset-callbacks . (,Side_position_interface::aligned_side))
(X-offset-callbacks . (,Self_alignment_interface::aligned_on_self))
(direction . 1)
+ (extra-offset . (-1 . 0))
(padding . 0.5)
(staff-padding . 0.5)
(script-priority . 200)
;;
-;; due to a bug in the GUILE evaluator,
-;; stack traces result in core dumps.
-;; therefore we retain debugging code.
-;;
-
-;;
-;; todo: this is too hairy.
+;; todo: this function is rather too hairy and too long.
;;
(define-public (determine-split-list evl1 evl2)
"EVL1 and EVL2 should be ascending"
-
+ (define pc-debug #f)
(define ev1 (list->vector evl1))
(define ev2 (list->vector evl2))
(define (when v i)
;;
(define (analyse-solo12 i1 i2 ri)
+ (define (put x)
+ (set-cdr! (vector-ref result ri) x) )
(cond
((= ri (vector-length result)) '())
((= i1 (vector-length ev1)) '())
((= i2 (vector-length ev2)) '())
(else
(let*
- (
+ ((now (when result ri))
(m1 (when ev1 i1))
(m2 (when ev2 i2))
- (notes1 (get-note-evs ev1 i1))
+ (notes1 (get-note-evs ev1
+ (if (ly:moment<? now m1)
+ (1- i1) i1)))
+
(durs1 (sort (map (lambda (x) (ly:get-mus-property x 'duration)) notes1) ly:duration<?))
(pitches1 (sort
(map (lambda (x) (ly:get-mus-property x 'pitch)) notes1) ly:pitch<?))
- (notes2 (get-note-evs ev2 i2))
+
+ (notes2 (get-note-evs ev2
+ (if (ly:moment<? now m2)
+ (1- i2) i2)))
+ (n2 (length notes2))
+ (n1 (length notes1))
(durs2 (sort (map (lambda (x) (ly:get-mus-property x 'duration)) notes2) ly:duration<?))
(pitches2 (sort
(map (lambda (x) (ly:get-mus-property x 'pitch)) notes2) ly:pitch<?))
)
+ (if pc-debug (display (list
+ "\n"
+ (when result ri) i1 "/" (vector-length ev1)
+ m1 ":" notes1
+ i2 "/" (vector-length ev2) m2 ":"
+ notes2
+ ri "/" (vector-length result) " = "
+ (what result ri)
+ "\n"
+ )))
+
+
+
(if (equal? (what result ri) 'apart)
(cond
- ((and (= 0 (length notes1))
- (< 0 (length notes2)))
- (set-cdr! (vector-ref result ri) 'solo2))
- ((and (< 0 (length notes1))
- (= 0 (length notes2)))
- (set-cdr! (vector-ref result ri) 'solo1))
+ ((and (= 0 n1)
+ (< 0 n2)
+ (equal? now m2)
+ )
+ (put 'solo2))
+ ((and (< 0 n1)
+ (= 0 n2)
+ (equal? now m1)
+ )
+ (put 'solo1))
+ ((and (= 0 n1)
+ (= 0 n2))
+ (put 'apart-silence))
))
(if (and
(equal? (what result ri) 'chords)
- (pair? pitches1)
(equal? pitches1 pitches2))
- (set-cdr! (vector-ref result ri) 'unisono) )
+ (put (if (pair? pitches2)
+ 'unisono 'unisilence) ))
(cond
((ly:moment<? m1 m2)
(analyse-time-step 0 0 0 '() '())
(analyse-solo12 0 0 0)
-; (display result)
+ (if pc-debug (display result))
+
(vector->list result))
(def-markup-command typewriter (markup?)
(font-markup 'font-family 'typewriter))
+(def-markup-command (doublesharp paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals-4")))
+(def-markup-command (threeqsharp paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals-3")))
+(def-markup-command (sharp paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals-2")))
+(def-markup-command (semisharp paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals-1")))
+(def-markup-command (natural paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals-0")))
+(def-markup-command (semiflat paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals--1")))
+(def-markup-command (flat paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals--2")))
+(def-markup-command (threeqflat paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals--3")))
+(def-markup-command (doubleflat paper props) ()
+ (interpret-markup paper props (markup #:musicglyph "accidentals--4")))
+
+
(def-markup-command (column paper props mrkups) (markup-list?)
(stack-lines
-1 0.0 (cdr (chain-assoc 'baseline-skip props))
conversions.append (((2,1,15), conv, """LyricsVoice . instr(ument) -> vocalName"""))
+def conv (str):
+ def sub_acc (m):
+ d = {
+ '4': 'doublesharp',
+ '3': 'threeqsharp',
+ '2': 'sharp',
+ '1': 'semisharp',
+ '0': 'natural',
+ '-1': 'semiflat',
+ '-2': 'flat',
+ '-3': 'threeqflat',
+ '-4': 'doubleflat'}
+ return '\\%s' % d[m.group (1)]
+
+ str = re.sub (r'\\musicglyph\s*#"accidentals-([0-9-]+)"',
+ sub_acc, str)
+ return str
+
+conversions.append (((2,1,16), conv, """\\musicglyph #"accidentals-NUM" -> \\sharp/flat/etc."""))
+
+
+def conv (str):
+ str = re.sub (r'\\context\s+Voice\s*=\s*one\s*\\partcombine\s+Voice\s*\\context\s+Thread\s*=\s*one(.*)\s*'
+ + r'\\context\s+Thread\s*=\s*two',
+ '\\\\newpartcombine\n\\1\n', str)
+ return str
+
+conversions.append (((2,1,17), conv, """\\partcombine -> \\newpartcombine"""))
+
################################
# END OF CONVERSIONS
################################