- 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.slur_dict = {}
- 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))
-
- sl = None
- try:
- sl = self.slur_dict[slurno]
- except KeyError:
- sl = Slur (slurno)
- self.slur_dict[slurno] = sl
-
- params = list (m.groups ()[1:])
- params = map (string.atoi, params)
- sl.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.calculate()
- try:
- m.global_measure = self.measures[mno]
- except IndexError:
- sys.stderr.write ("non-existent global measure %d" % mno)
- continue
-
- 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.slur_dict.values():
- s.calculate (self.chords)
- for s in self.articulations[1:]:
- s.calculate (self.chords)
-
- def get_thread (self, startno, endno):
-
- thread = []
-
- c = None
- try:
- c = self.chords[startno]
- except IndexError:
- sys.stderr.write ("Huh? Frame has invalid bounds (%d,%d)\n" % (startno, endno))
- return []
-
-
- 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 identify():
- sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
+ def __init__ (self, number, contents):
+ self.pitches = []
+ self.frame = None
+ self.finale = contents[:7]
+
+ self.notelist = ziplist (contents[7:])
+ self.duration = None
+ self.next = None
+ self.prev = None
+ self.number = number
+ 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 EDU_duration (self):
+ return self.finale[2]
+ def set_duration (self):
+ self.duration = EDU_to_duration(self.EDU_duration ())
+
+ def calculate (self):
+ self.find_realpitch ()
+ self.set_duration ()
+
+ flag = self.finale[4]
+ if Chord.GRACE_MASK & flag:
+ self.grace = 1
+
+
+ def find_realpitch (self):
+
+ meas = self.measure ()
+ tiestart = 0
+ if not meas or not meas.global_measure :
+ sys.stderr.write ('note %d not in measure\n' % self.number)
+ elif not meas.global_measure.scale:
+ sys.stderr.write ('note %d: no scale in this measure.' % self.number)
+ else:
+
+ for p in self.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[4] & 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 + nn
+
+ if not self.pitches:
+ s = 'r'
+ if len (self.pitches) > 1:
+ s = '<%s>' % s
+
+ s = s + '%d%s' % (self.duration[0], '.'* self.duration[1])
+ s = self.note_prefix + s + self.note_suffix
+
+ s = self.chord_prefix + s + self.chord_suffix
+
+ return s
+
+
+def fill_list_to (list, no):
+ """
+Add None to LIST until it contains entry number NO.
+ """
+ while len (list) <= no:
+ list.extend ([None] * (no - len(list) + 1))
+ return list
+
+def read_finale_value (str):
+ """
+Pry off one value from STR. The value may be $hex, decimal, or "string".
+Return: (value, rest-of-STR)
+ """
+ while str and str[0] in ' \t\n':
+ str = str[1:]
+
+ if not str:
+ return (None,str)
+
+ if str[0] == '$':
+ str = str [1:]
+
+ hex = ''
+ while str and str[0] in '0123456789ABCDEF':
+ hex = hex + str[0]
+ str = str[1:]
+
+
+ return (long (hex, 16), str)
+ elif str[0] == '"':
+ str = str[1:]
+ s = ''
+ while str and str[0] <> '"':
+ s = s + str[0]
+ str = str[1:]
+
+ return (s,str)
+ elif str[0] in '-0123456789':
+ dec = ''
+ while str and str[0] in '-0123456789':
+ dec = dec + str[0]
+ str = str[1:]
+
+ return (int (dec), str)
+ else:
+ sys.stderr.write ("cannot convert `%s'\n" % str)
+ return (None, str)
+
+
+
+
+def parse_etf_file (fn, tag_dict):
+
+ """ Read FN, putting ETF info into
+ a giant dictionary. The keys of TAG_DICT indicate which tags
+ to put into the dict.
+ """
+
+ sys.stderr.write ('parsing ... ' )
+ f = open (fn)
+
+ gulp = re.sub ('[\n\r]+', '\n', f.read ())
+ ls = gulp.split ('\n^')
+
+ etf_file_dict = {}
+ for k in tag_dict:
+ etf_file_dict[k] = {}
+
+ last_tag = None
+ last_numbers = None
+
+
+ for l in ls:
+ m = re.match ('^([a-zA-Z0-9&]+)\(([^)]+)\)', l)
+ if m and tag_dict.has_key (m.group (1)):
+ tag = m.group (1)
+
+ indices = tuple ([int (s) for s in m.group (2).split (',')])
+ content = l[m.end (2)+1:]
+
+
+ tdict = etf_file_dict[tag]
+ if not tdict.has_key (indices):
+ tdict[indices] = []
+