From efaf6bd61c89103205039c82fbcfc4d9ab1bb55e Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Thu, 31 Aug 2000 18:29:54 +0200 Subject: [PATCH] patch::: 1.3.82.hwn1 1.3.82.hwn1 =========== * comment in some unprotects for Music in parser. Should bring down cpu time and plug some leaks. * robustness fixes for etf2ly, tuplets, grace notes. --- CHANGES | 9 ++ VERSION | 2 +- lily/bezier.cc | 7 ++ lily/music-sequence.cc | 2 + lily/music-wrapper.cc | 1 + lily/parser.yy | 9 +- lily/part-combine-music.cc | 4 +- lily/repeated-music.cc | 3 + scripts/etf2ly.py | 173 +++++++++++++++++++++++++++++++------ 9 files changed, 179 insertions(+), 31 deletions(-) diff --git a/CHANGES b/CHANGES index cb52b11d60..ac2b7778ce 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ + +1.3.82.hwn1 +=========== + +* comment in some unprotects for Music in parser. Should bring down + cpu time and plug some leaks. + +* robustness fixes for etf2ly, tuplets, grace notes. + 1.3.82 ====== diff --git a/VERSION b/VERSION index 7992718877..f51aeee26b 100644 --- a/VERSION +++ b/VERSION @@ -2,7 +2,7 @@ PACKAGE_NAME=LilyPond MAJOR_VERSION=1 MINOR_VERSION=3 PATCH_LEVEL=82 -MY_PATCH_LEVEL= +MY_PATCH_LEVEL=hwn1 # use the above to send patches: MY_PATCH_LEVEL is always empty for a # released version. diff --git a/lily/bezier.cc b/lily/bezier.cc index faf5b899a2..21c49801b5 100644 --- a/lily/bezier.cc +++ b/lily/bezier.cc @@ -8,6 +8,7 @@ #include #include "config.h" +#include "warn.hh" #include "libc-extension.hh" #include "bezier.hh" @@ -65,6 +66,12 @@ Bezier::get_other_coordinate (Axis a, Real x) const { Axis other = Axis ((a +1)%NO_AXES); Array ts = solve_point (a, x); + + if (ts.size () == 0) + { + programming_error ("No solution found for Bezier intersection."); + return 0.0; + } Offset c = curve_point (ts[0]); assert (fabs (c[a] - x) < 1e-8); diff --git a/lily/music-sequence.cc b/lily/music-sequence.cc index 32c386c323..3ff7f4a235 100644 --- a/lily/music-sequence.cc +++ b/lily/music-sequence.cc @@ -48,7 +48,9 @@ Music_sequence::append_music (Music *m) { set_mus_property ("list", gh_append2( music_list(), gh_cons (m->self_scm (), SCM_EOL))); + scm_unprotect_object (m->self_scm ()); } + Music_sequence::Music_sequence(SCM h) { set_mus_property ("list", h); diff --git a/lily/music-wrapper.cc b/lily/music-wrapper.cc index 641c83b91b..8a2d66f5bd 100644 --- a/lily/music-wrapper.cc +++ b/lily/music-wrapper.cc @@ -28,6 +28,7 @@ Music_wrapper::transpose (Musical_pitch p) Music_wrapper::Music_wrapper(Music*p) { set_mus_property ("element", p->self_scm ()); + scm_unprotect_object (p->self_scm ()); } Moment diff --git a/lily/parser.yy b/lily/parser.yy index 84a0b042d8..3c4ff7b867 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -365,8 +365,6 @@ assignment: /* TODO: devise standard for protection in parser. - if (SCM_NIMP($4)) - scm_unprotect_object ($4); The parser stack lives on the C-stack, which means that all objects can be unprotected as soon as they're here. @@ -389,12 +387,15 @@ identifier_init: } | translator_spec_block { $$ = $1->self_scm (); + scm_unprotect_object ($$); } | Music { $$ = $1->self_scm (); + scm_unprotect_object ($$); } | post_request { $$ = $1->self_scm (); + scm_unprotect_object ($$); } | explicit_duration { $$ = (new Duration_identifier ($1, DURATION_IDENTIFIER))->self_scm (); @@ -502,7 +503,7 @@ score_body: $$->set_spot (THIS->here_input ()); SCM m = $1->self_scm (); -// scm_unprotect_object (m); + scm_unprotect_object (m); $$->music_ = m; } | SCORE_IDENTIFIER { @@ -603,7 +604,7 @@ Music_list: /* empty */ { | Music_list Music { SCM s = $$; SCM c = gh_cons ($2->self_scm (), SCM_EOL); -// scm_unprotect_object ($2->self_scm ()); /* UGH */ + scm_unprotect_object ($2->self_scm ()); /* UGH */ if (gh_pair_p (gh_cdr (s))) diff --git a/lily/part-combine-music.cc b/lily/part-combine-music.cc index 27064244b7..d9e98329b3 100644 --- a/lily/part-combine-music.cc +++ b/lily/part-combine-music.cc @@ -15,8 +15,10 @@ Part_combine_music::Part_combine_music (String what, Music * f, Music * s) what_str_ = what; set_mus_property ("one", f->self_scm ()); set_mus_property ("two", s->self_scm ()); -} + scm_unprotect_object (f->self_scm()); + scm_unprotect_object (s->self_scm()); +} void Part_combine_music::transpose (Musical_pitch p) diff --git a/lily/repeated-music.cc b/lily/repeated-music.cc index 2e8e0e3d02..f817ab0d33 100644 --- a/lily/repeated-music.cc +++ b/lily/repeated-music.cc @@ -35,6 +35,9 @@ Repeated_music::Repeated_music(Music *beg, int times, Music_sequence * alts) alts->truncate (times); set_mus_property ("alternatives", alts->self_scm ()); } + + scm_unprotect_object (beg->self_scm ()); + scm_unprotect_object (alts->self_scm ()); } Repeated_music::Repeated_music (Repeated_music const &s) diff --git a/scripts/etf2ly.py b/scripts/etf2ly.py index b194f28561..3363872a42 100644 --- a/scripts/etf2ly.py +++ b/scripts/etf2ly.py @@ -11,15 +11,18 @@ # * slurs # * lyrics # * articulation -# +# * grace notes +# * tuplets + # todo: -# * automatic PC/mac/unix conversion # * slur/stem directions # * voices (2nd half of frame?) # * more intelligent lyrics # * beams (better use autobeam?) -# * more robust: try entertainer.etf (freenote), schubert ave maria (gmd) +# * more robust: try entertainer.etf (freenote) +# * dynamics +# program_name = 'etf2ly' version = '@TOPLEVEL_VERSION@' @@ -142,6 +145,44 @@ def lily_notename (tuple2): return nn +class Tuplet: + def __init__ (self, number): + self.start_note = number + self.finale = [] + + def append_finale (self, fin): + self.finale.append (fin) + + def factor (self): + n = self.finale[0][2]*self.finale[0][3] + d = self.finale[0][0]*self.finale[0][1] + return rat_simplify( (n, d)) + + def dump_start (self): + return '\\times %d/%d { ' % self.factor () + + def dump_end (self): + return ' }' + + def calculate (self, chords): + edu_left = self.finale[0][0] * self.finale[0][1] + + startch = chords[self.start_note] + c = startch + while c and edu_left: + c.tuplet = self + if c == startch: + c.chord_prefix = self.dump_start () + c.chord_prefix + + if not c.grace: + edu_left = edu_left - c.EDU_duration () + if edu_left == 0: + c.chord_suffix = c.chord_suffix+ self.dump_end () + c = c.next + + if edu_left: + sys.stderr.write ("\nHuh? Tuplet starting at entry %d was too short." % self.start_note) + class Slur: def __init__ (self, number): self.number = number @@ -163,8 +204,7 @@ class Slur: cs.note_suffix = '(' + cs.note_suffix ce.note_prefix = ce.note_prefix + ')' except IndexError: - sys.stderr.write ("""\nHuh? Incorrect slur start/endpoint -len(list) is %d, start/end is (%d,%d)\n""" % (len (chords), startnote, endnote)) + sys.stderr.write ("""\nHuh? Slur no %d between (%d,%d), with %d notes""" % (self.number, startnote, endnote, len (chords))) class Global_measure: @@ -198,6 +238,7 @@ articulation_dict ={ 11: '\\prall', 12: '\\mordent', 8: '\\fermata', + 4: '^', 18: '"arp"' , # arpeggio }; @@ -211,6 +252,7 @@ class Articulation: try: a = articulation_dict[self.type] except KeyError: + sys.stderr.write ("\nUnknown articulation %d" % self.type) a = '"art"' c.note_suffix = '-' + a + c.note_suffix @@ -299,22 +341,43 @@ class Frame: def set_measure (self, m): self.measure = m + def calculate (self): + + # do grace notes. + lastch = None + for c in self.chords: + if c.grace and (lastch == None or (not lastch.grace)): + c.chord_prefix = r'\grace {' + c.chord_prefix + elif not c.grace and lastch and lastch.grace: + lastch.chord_suffix = lastch.chord_suffix + ' } ' + + lastch = c + + + def dump (self): - str = '' + str = '%% FR(%d)\n' % self.number left = self.measure.global_measure.length () + + + ln = '' for c in self.chords: - str = str + c.ly_string () + ' ' + add = c.ly_string () + ' ' + if len (ln) + len(add) > 72: + str = str + ln + '\n' + ln = '' + ln = ln + add left = rat_subtract (left, c.length ()) - + + str = str + ln + if left[0] < 0: - sys.stderr.write ("""Huh? Going backwards. -Frame no %d, start/end (%d,%d) -""" % (self.number, self.start, self.end)) + sys.stderr.write ("""\nHuh? Going backwards in frame no %d, start/end (%d,%d)""" % (self.number, self.start, self.end)) left = (0,1) if left[0]: - str = str + 's*%d/%d' % left - - str = str + '\n' + str = str + rat_to_lily_duration (left) + + str = str + ' | \n' return str def encodeint (i): @@ -364,7 +427,7 @@ class Staff: last_clef = m.clef if e: if gap <> (0,1): - k = k +' s1*%d/%d \n ' % gap + k = k +' ' + rat_to_lily_duration (gap) + '\n' gap = (0,1) k = k + e @@ -393,7 +456,7 @@ class Staff: if fr: first_frame = fr if gap <> (0,1): - laystr = laystr +'} s1*%d/%d {\n ' % gap + laystr = laystr +'} %s {\n ' % rat_to_lily_duration (gap) gap = (0,1) laystr = laystr + fr.dump () else: @@ -431,6 +494,23 @@ def EDU_to_duration (edu): dots = 2 return (log, dots) +def rat_to_lily_duration (rat): + (n,d) = rat + + basedur = 1 + while d and d % 2 == 0: + basedur = basedur << 1 + d = d >> 1 + + str = 's%d' % basedur + if n <> 1: + str = str + '*%d' % n + if d <> 1: + str = str + '/%d' % d + + return str + + class Chord: def __init__ (self, finale_entry): self.pitches = [] @@ -443,6 +523,8 @@ class Chord: self.note_suffix = '' self.chord_suffix = '' self.chord_prefix = '' + self.tuplet = None + self.grace = 0 def measure (self): if not self.frame: @@ -450,19 +532,36 @@ class Chord: return self.frame.measure def length (self): + if self.grace: + return (0,1) + l = (1, self.duration[0]) d = 1 << self.duration[1] dotfact = rat_subtract ((2,1), (1,d)) - return rat_multiply (dotfact, l) + mylen = rat_multiply (dotfact, l) + + if self.tuplet: + mylen = rat_multiply (mylen, self.tuplet.factor()) + return mylen def number (self): return self.finale[0][0] + + def EDU_duration (self): + return self.finale[0][3] def set_duration (self): - ((no, prev, next, dur, pos, entryflag, extended, follow), - notelist) = self.finale - self.duration = EDU_to_duration(dur) + self.duration = EDU_to_duration(self.EDU_duration ()) + def calculate (self): + self.find_realpitch () + self.set_duration () + + flag = self.finale[0][5] + if Chord.GRACE_MASK & flag: + self.grace = 1 + + def find_realpitch (self): ((no, prev, next, dur, pos, entryflag, extended, follow), notelist) = self.finale @@ -493,6 +592,8 @@ class Chord: REST_MASK = 0x40000000L TIE_START_MASK = 0x40000000L + GRACE_MASK = 0x00800000L + def ly_string (self): s = '' @@ -541,12 +642,16 @@ IMre = re.compile (r"""^\^IM\(([0-9-]+),([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+ vere = re.compile(r"""^\^(ve|ch|se)\(([0-9-]+),([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""") versere = re.compile(r"""^\^verse\(([0-9]+)\)(.*)\^end""") +TPre = re.compile(r"""^\^TP\(([0-9]+),([0-9]+)\) *([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""") + + class Etf_file: def __init__ (self, name): self.measures = [None] self.entries = [None] self.chords = [None] self.frames = [None] + self.tuplets = [None] self.staffs = [None] self.slurs = [None] self.articulations = [None] @@ -585,7 +690,17 @@ class Etf_file: bn = string.atoi (m.group (1)) where = string.atoi (m.group (2)) / 1024.0 return m + def try_TP(self, l): + m = TPre.match (l) + if m: + (nil, num) = map (string.atoi, (m.groups ()[0:2])) + entries = map (string.atoi, (m.groups ()[2:])) + + if self.tuplets[-1] == None or num <> self.tuplets[-1].start_note: + self.tuplets.append (Tuplet (num)) + self.tuplets[-1].append_finale (entries) + def try_IM (self, l): m = IMre.match (l) if m: @@ -627,7 +742,7 @@ class Etf_file: entryflag = string.atol (entryflag,16) if no > len (self.entries): - sys.stderr.write ("Huh? Entry number to large,\nexpected %d got %d. Filling with void entries.\n" % (len(self.entries), no )) + sys.stderr.write ("\nHuh? Entry number to large,\nexpected %d got %d. Filling with void entries.\n" % (len(self.entries), no )) while len (self.entries) <> no: c = ((len (self.entries), 0, 0, 0, 0, 0L, 0, 0), []) self.entries.append (c) @@ -722,6 +837,8 @@ class Etf_file: m = self.try_IM (l) if not m: m = self.try_Sx (l) + if not m: + m = self.try_TP (l) if not m: m = self.try_verse (l) @@ -759,8 +876,13 @@ class Etf_file: mno = mno + 1 for c in self.chords[1:]: - c.find_realpitch () - c.set_duration () + c.calculate() + + for f in self.frames[1:]: + f.calculate () + + for t in self.tuplets[1:]: + t.calculate (self.chords) for s in self.slurs [1:]: s.calculate (self.chords) @@ -788,8 +910,6 @@ class Etf_file: str = str + '\n\n' + s.dump () staffs.append ('\\' + s.staffid ()) - if staffs: - str = str + '\\score { < %s > } ' % string.join (staffs) # should use \addlyrics ? @@ -799,6 +919,9 @@ class Etf_file: if len (self.verses) > 1: sys.stderr.write ("\nLyrics found; edit to use \\addlyrics to couple to a staff\n") + if staffs: + str = str + '\\score { < %s > } ' % string.join (staffs) + return str -- 2.39.5