]> git.donarmstrong.com Git - lilypond.git/commitdiff
patch::: 1.3.82.hwn1
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 31 Aug 2000 16:29:54 +0000 (18:29 +0200)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Thu, 31 Aug 2000 16:29:54 +0000 (18:29 +0200)
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
VERSION
lily/bezier.cc
lily/music-sequence.cc
lily/music-wrapper.cc
lily/parser.yy
lily/part-combine-music.cc
lily/repeated-music.cc
scripts/etf2ly.py

diff --git a/CHANGES b/CHANGES
index cb52b11d60c35ee7f6215091abbeef9c39166cc2..ac2b7778ce9df8050ef9e31d158cace7a27f4340 100644 (file)
--- 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 7992718877f49b3b86f3f4ba1c146faaff4c8eb8..f51aeee26b7db45c5451b87e93ab7497da8cf221 100644 (file)
--- 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.
index faf5b899a2662a5c0aaabc347620d1298a97d2e2..21c49801b54dc19fbadab5c72864dba763b5ddf8 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <math.h>
 #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<Real> 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);
index 32c386c323df7e3fcdcb41091ac8a6093f44564c..3ff7f4a235d20fe6879a1f59b7f774997fc8d813 100644 (file)
@@ -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);
index 641c83b91ba32d5256186f79230a6d95deeaa95a..8a2d66f5bd4f459328e7552cf47796e74e154ac7 100644 (file)
@@ -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
index 84a0b042d82afc4df8aba23e0942d9cacfa40d6a..3c4ff7b86787cebe7122644055f1e06aa4ff6d0e 100644 (file)
@@ -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)))
index 27064244b7628996c83685b30524affc92cf8581..d9e98329b3be75126a6068f0c7d1a424eaf255bb 100644 (file)
@@ -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)
index 2e8e0e3d0204ece0397d25e1b17a86c6d2ffebd6..f817ab0d3332d1f41871fa87b02af96c68c91d6d 100644 (file)
@@ -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)
index b194f285614f32fc5446ae567a6e5e5473550f00..3363872a4252fbce580b679f1ce4d4fa8c93dbb8 100644 (file)
 #  * 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