- def __init__ (self, number):
- self.number = number
- self.measures = []
-
- def get_measure (self, no):
- if len (self.measures) <= no:
- self.measures = self.measures + [None]* (1 + no - len (self.measures))
-
- if self.measures[no] == None:
- m = Measure (no)
- self.measures [no] =m
- m.staff = self
-
-
- return self.measures[no]
- def staffid (self):
- return 'staff' + encodeint (self.number - 1)
- def layerid (self, l):
- return self.staffid() + 'layer%s' % chr (l -1 + ord ('A'))
-
- def dump_time_key_sigs (self):
- k = ''
- last_key = None
- last_time = None
- last_clef = None
- gap = (0,1)
- for m in self.measures[1:]:
- if not m :
- continue # ugh.
-
- g = m.global_measure
- e = ''
- if last_key <> g.keysignature:
- e = e + "\\key %s \\major; " % lily_notename (g.keysignature)
- last_key = g.keysignature
- if last_time <> g.timesig :
- e = e + "\\time %d/%d; " % g.timesig
- last_time = g.timesig
- if last_clef <> m.clef :
- e = e + '\\clef %s;' % lily_clef (m.clef)
- last_clef = m.clef
- if e:
- if gap <> (0,1):
- k = k +' ' + rat_to_lily_duration (gap) + '\n'
- gap = (0,1)
- k = k + e
-
- gap = rat_add (gap, g.length ())
-
-
- k = '%sglobal = \\notes { %s }\n\n ' % (self.staffid (), k)
- return k
-
- def dump (self):
- str = ''
-
-
- layerids = []
- for x in range (1,5): # 4 layers.
- laystr = ''
- last_frame = None
- first_frame = None
- gap = (0,1)
- for m in self.measures[1:]:
- if not m:
- continue
-
-
- fr = m.frames[x]
- if fr:
- first_frame = fr
- if gap <> (0,1):
- laystr = laystr +'} %s {\n ' % rat_to_lily_duration (gap)
- gap = (0,1)
- laystr = laystr + fr.dump ()
- else:
- gap = rat_add (gap, m.global_measure.length ())
-
- if first_frame:
- l = self.layerid (x)
- laystr = '%s = \\notes { { %s } }\n\n' % (l, laystr)
- str = str + laystr
- layerids.append (l)
-
- str = str + self.dump_time_key_sigs ()
- stafdef = '\\%sglobal' % self.staffid ()
- for i in layerids:
- stafdef = stafdef + ' \\' + i
-
-
- str = str + '%s = \\context Staff = %s <\n %s\n >\n' % \
- (self.staffid (), self.staffid (), stafdef)
- return str
-
-
-def EDU_to_duration (edu):
- log = 1
- d = 4096
- while d > edu:
- d = d >> 1
- log = log << 1
-
- edu = edu - d
- dots = 0
- if edu == d /2:
- dots = 1
- elif edu == d*3/4:
- 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 = []
- self.frame = None
- self.finale = finale_entry
- self.duration = None
- self.next = None
- self.prev = None
- self.note_prefix= ''
- self.note_suffix = ''
- self.chord_suffix = ''
- self.chord_prefix = ''
- self.tuplet = None
- self.grace = 0
-
- def measure (self):
- if not self.frame:
- return None
- 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))
- 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):
- 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
-
- meas = self.measure ()
- tiestart = 0
- if not meas or not meas.global_measure :
- print 'note %d not in measure' % self.number ()
- elif not meas.global_measure.scale:
- print 'note %d: no scale in this measure.' % self.number ()
- else:
- for p in notelist:
- (pitch, flag) = p
-
- nib1 = pitch & 0x0f
- if nib1 > 8:
- nib1 = -(nib1 - 8)
- rest = pitch / 16
-
- scale = meas.global_measure.scale
- (sn, sa) =scale[rest % 7]
- sn = sn + (rest - (rest%7)) + 7
- acc = sa + nib1
- self.pitches.append ((sn, acc))
- tiestart = tiestart or (flag & Chord.TIE_START_MASK)
- if tiestart :
- self.chord_suffix = self.chord_suffix + ' ~ '
-
- REST_MASK = 0x40000000L
- TIE_START_MASK = 0x40000000L
- GRACE_MASK = 0x00800000L
-
- def ly_string (self):
- s = ''
-
- rest = ''
-
- if not (self.finale[0][5] & Chord.REST_MASK):
- rest = 'r'
-
- for p in self.pitches:
- (n,a) = p
- o = n/ 7
- n = n % 7
-
- nn = lily_notename ((n,a))
-
- if o < 0:
- nn = nn + (',' * -o)
- elif o > 0:
- nn = nn + ('\'' * o)
-
- if s:
- s = s + ' '
-
- if rest:
- nn = rest
-
- s = s + '%s%d%s' % (nn, self.duration[0], '.'* self.duration[1])
-
- if not self.pitches:
- s = 'r%d%s' % (self.duration[0] , '.'* self.duration[1])
- s = self.note_prefix + s + self.note_suffix
- if len (self.pitches) > 1:
- s = '<%s>' % s
-
- s = self.chord_prefix + s + self.chord_suffix
- return s
-
-GFre = re.compile(r"""^\^GF\(([0-9-]+),([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""")
-BCre = re.compile (r"""^\^BC\(([0-9-]+)\) ([0-9-]+) .*$""")
-eEre = re.compile(r"""^\^eE\(([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) \$([0-9A-Fa-f]+) ([0-9-]+) ([0-9-]+)""")
-FRre = re.compile (r"""^\^FR\(([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""")
-MSre = re.compile (r"""^\^MS\(([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""")
-note_re = re.compile (r"""^ +([0-9-]+) \$([A-Fa-f0-9]+)""")
-Sxre = re.compile (r"""^\^Sx\(([0-9-]+)\) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+) ([0-9-]+)""")
-IMre = re.compile (r"""^\^IM\(([0-9-]+),([0-9-]+)\) ([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]
- self.syllables = [None]
- self.verses = [None]
-
- ## do it
- self.parse (name)
-
- def get_global_measure (self, no):
- if len (self.measures) <= no:
- self.measures = self.measures + [None]* (1 + no - len (self.measures))
-
- if self.measures[no] == None:
- self.measures [no] = Global_measure (no)
-
- return self.measures[no]
-
-
- def get_staff(self,staffno):
- if len (self.staffs) <= staffno:
- self.staffs = self.staffs + [None] * (1 + staffno - len (self.staffs))
-
- if self.staffs[staffno] == None:
- self.staffs[staffno] = Staff (staffno)
-
- return self.staffs[staffno]
-
- # staff-spec
- def try_IS (self, l):
- pass
-
- def try_BC (self, l):
- m = BCre.match (l)
- if m:
- 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:
- a = string.atoi (m.group (1))
- b = string.atoi (m.group (2))
-
- fin = map (string.atoi, m.groups ()[2:])
-
- self.articulations.append (Articulation (a,b,fin))
- return m
- def try_verse (self,l):
- m = versere .match (l)
- if m:
- a = string.atoi (m.group (1))
- body =m.group (2)
-
- body = re.sub (r"""\^[a-z]+\([^)]+\)""", "", body)
- body = re.sub ("\^[a-z]+", "", body)
- self.verses.append (Verse (a, body))
-
- return m
- def try_ve (self,l):
- m = vere .match (l)
- if m:
- a = string.atoi (m.group (1))
- b = string.atoi (m.group (2))
-
- fin = map (string.atoi, m.groups ()[2:])
-
- self.syllables.append (Syllable (a,b,fin))
- return m
- def try_eE (self, l):
- m = eEre.match (l)
- if m:
- tup = m.groups()
- (no, prev, next, dur, pos, entryflag, extended, follow) = tup
- (no, prev, next, dur, pos,extended, follow) \
- = tuple (map (string.atoi, [no,prev,next,dur,pos,extended,follow]))
-
- entryflag = string.atol (entryflag,16)
- if no > len (self.entries):
- 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)
-
- current_entry = ((no, prev, next, dur, pos, entryflag, extended, follow), [])
- self.entries.append (current_entry)
- return m
-
- def try_Sx(self,l):
- m = Sxre.match (l)
- if m:
- slurno = string.atoi (m.group (1))
-
- if len (self.slurs) == slurno:
- self.slurs.append (Slur (slurno))
-
- params = list (m.groups ()[1:])
- params = map (string.atoi, params)
- self.slurs[-1].append_entry (params)
-
- return m
- def try_GF(self, l):
- m = GFre.match (l)
- if m:
- (staffno,measno) = m.groups ()[0:2]
- s = string.atoi (staffno)
- me = string.atoi (measno)
-
- entry = m.groups () [2:]
- st = self.get_staff (s)
- meas = st.get_measure (me)
- meas.add_finale_entry (entry)
-
- # frame ?
- def try_FR(self, l):
- m = FRre.match (l)
- if m:
- (frameno, startnote, endnote, foo, bar) = m.groups ()
- (frameno, startnote, endnote) = tuple (map (string.atoi, [frameno, startnote, endnote]))
- if frameno > len (self.frames):
- sys.stderr.write ("Frame no %d missing, filling up to %d\n" % (len(self.frames), frameno))
- while frameno <> len (self.frames):
- self.frames.append (Frame ((len (self.frames), 0,0) ))
-
- self.frames.append (Frame ((frameno, startnote, endnote)))
-
- return m
- def try_MS (self, l):
- m = MSre.match (l)
- if m:
- measno = string.atoi (m.group (1))
- keynum = string.atoi (m.group (3))
- meas =self. get_global_measure (measno)
- meas.set_keysig (keynum)
-
- beats = string.atoi (m.group (4))
- beatlen = string.atoi (m.group (5))
- meas.set_timesig ((beats, beatlen))
-
- return m
-
- def try_note (self, l):
- m = note_re.match (l)
- if m:
- (pitch, flag) = m.groups ()
- pitch = string.atoi (pitch)
- flag = string.atol (flag,16)
- self.entries[-1][1].append ((pitch,flag))
-
- def parse (self, name):
- sys.stderr.write ('parsing ...')
- sys.stderr.flush ()
-
- gulp = open (name).read ()
-
- gulp = re.sub ('[\n\r]+', '\n', gulp)
- ls = string.split (gulp, '\n')
-
- for l in ls:
- m = None
- if not m:
- m = self.try_MS (l)
- if not m:
- m = self.try_FR (l)
- if not m:
- m = self.try_GF (l)
- if not m:
- m = self.try_note (l)
- if not m:
- m = self.try_eE (l)
- if not m:
- 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)
-
- sys.stderr.write ('processing ...')
- sys.stderr.flush ()
-
- self.unthread_entries ()
-
- for st in self.staffs[1:]:
- if not st:
- continue
- mno = 1
- for m in st.measures[1:]:
- if not m:
- continue
-
- m.global_measure = self.measures[mno]
- m.calculate()
-
- frame_obj_list = [None]
- for frno in m.frames:
- fr = self.frames[frno]
- frame_obj_list.append (fr)
-
- m.frames = frame_obj_list
- for fr in frame_obj_list[1:]:
- if not fr:
- continue
-
- fr.set_measure (m)
-
- fr.chords = self.get_thread (fr.start, fr.end)
- for c in fr.chords:
- c.frame = fr
- mno = mno + 1
-
- for c in self.chords[1:]:
- 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)
- for s in self.articulations[1:]:
- s.calculate (self.chords)
-
- def get_thread (self, startno, endno):
-
- thread = []
- c = self.chords[startno]
- while c and c.number () <> endno:
- thread.append (c)
- c = c.next
-
- if c:
- thread.append (c)
-
- return thread
-
- def dump (self):
- str = ''
- staffs = []
- for s in self.staffs[1:]:
- if s:
- str = str + '\n\n' + s.dump ()
- staffs.append ('\\' + s.staffid ())
-
-
- # should use \addlyrics ?
-
- for v in self.verses[1:]:
- str = str + v.dump()
-
- 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
-
-
- def __str__ (self):
- return 'ETF FILE %s %s' % (self.measures, self.entries)
-
- def unthread_entries (self):
- self.chords = [None]
- for e in self.entries[1:]:
- self.chords.append (Chord (e))
-
- for e in self.chords[1:]:
- e.prev = self.chords[e.finale[0][1]]
- e.next = self.chords[e.finale[0][2]]
-
-
-
+ def __init__ (self, number):
+ self.number = number
+ self.measures = []
+
+ def get_measure (self, no):
+ fill_list_to (self.measures, no)
+
+ if self.measures[no] == None:
+ m = Measure (no)
+ self.measures [no] =m
+ m.staff = self
+
+ return self.measures[no]
+ def staffid (self):
+ return 'staff' + encodeint (self.number - 1)
+ def layerid (self, l):
+ return self.staffid() + 'layer%s' % chr (l -1 + ord ('A'))
+
+ def dump_time_key_sigs (self):
+ k = ''
+ last_key = None
+ last_time = None
+ last_clef = None
+ gap = (0,1)
+ for m in self.measures[1:]:
+ if not m or not m.valid:
+ continue # ugh.
+
+ g = m.global_measure
+ e = ''
+
+ if g:
+ if g.key_signature and not g.key_signature.equal(last_key):
+ pitch= g.key_signature.pitch
+ e = e + "\\key %s %s " % (lily_notename (pitch),
+ g.key_signature.signature_type())
+
+ last_key = g.key_signature
+ if last_time <> g.timesig :
+ e = e + "\\time %d/%d " % g.timesig
+ last_time = g.timesig
+
+ if 'start' in g.repeats:
+ e = e + ' \\bar "|:" '
+
+
+ # we don't attempt voltas since they fail easily.
+ if 0 : # and g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket:
+ strs = []
+ if g.repeat_bar == '|:' or g.repeat_bar == ':|:' or g.bracket == 'end':
+ strs.append ('#f')
+
+
+ if g.bracket == 'start':
+ strs.append ('"0."')
+
+ str = ' '.join (['(volta %s)' % x for x in strs])
+
+ e = e + ' \\set Score.repeatCommands = #\'(%s) ' % str
+
+ if g.force_break:
+ e = e + ' \\break '
+
+ if last_clef <> m.clef :
+ e = e + '\\clef "%s"' % lily_clef (m.clef)
+ last_clef = m.clef
+ if e:
+ if gap <> (0,1):
+ k = k +' ' + rational_to_lily_skip (gap) + '\n'
+ gap = (0,1)
+ k = k + e
+
+ if g:
+ gap = rat_add (gap, g.length ())
+ if 'stop' in g.repeats:
+ k = k + ' \\bar ":|" '
+
+ k = '%sglobal = { %s }\n\n ' % (self.staffid (), k)
+ return k
+
+ def dump (self):
+ str = ''
+
+
+ layerids = []
+ for x in range (1,5): # 4 layers.
+ laystr = ''
+ last_frame = None
+ first_frame = None
+ gap = (0,1)
+ for m in self.measures[1:]:
+ if not m or not m.valid:
+ sys.stderr.write ("Skipping non-existant or invalid measure\n")
+ continue
+
+ fr = None
+ try:
+ fr = m.frames[x]
+ except IndexError:
+ sys.stderr.write ("Skipping nonexistent frame %d\n" % x)
+ laystr = laystr + "%% non existent frame %d (skipped) \n" % x
+ if fr:
+ first_frame = fr
+ if gap <> (0,1):
+ laystr = laystr +'} %s {\n ' % rational_to_lily_skip (gap)
+ gap = (0,1)
+ laystr = laystr + fr.dump ()
+ else:
+ if m.global_measure :
+ gap = rat_add (gap, m.global_measure.length ())
+ else:
+ sys.stderr.write ( \
+ "No global measure for staff %d measure %d\n"
+ % (self.number, m.number))
+ if first_frame:
+ l = self.layerid (x)
+ laystr = '%s = { { %s } }\n\n' % (l, laystr)
+ str = str + laystr
+ layerids.append (l)
+
+ str = str + self.dump_time_key_sigs ()
+ stafdef = '\\%sglobal' % self.staffid ()
+ for i in layerids:
+ stafdef = stafdef + ' \\' + i
+
+
+ str = str + '%s = \\context Staff = %s <<\n %s\n >>\n' % \
+ (self.staffid (), self.staffid (), stafdef)
+ return str
+
+
+
+def ziplist (l):
+ if len (l) < 2:
+ return []
+ else:
+ return [(l[0], l[1])] + ziplist (l[2:])