X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fetf2ly.py;h=225d23397b5ccd1c03ba62b5d5b0d2a63156cdfe;hb=75eebcb49e52d296b1da3e1074e0825d2c780db4;hp=f80334bc14d7dac35c0f4953e79d63b7ca4c8d8d;hpb=5f68ba5ca0edd64f0f6723e65c27993c2dfb1e96;p=lilypond.git diff --git a/scripts/etf2ly.py b/scripts/etf2ly.py index f80334bc14..225d23397b 100644 --- a/scripts/etf2ly.py +++ b/scripts/etf2ly.py @@ -1,7 +1,7 @@ #!@PYTHON@ # info mostly taken from looking at files. See also -# http://www.cs.uu.nl/~hanwen/lily-devel/etf.html +# http://lilypond.org/wiki/?EnigmaTransportFormat # This supports # @@ -24,13 +24,8 @@ # * dynamics # * empty measures (eg. twopt03.etf from freenote) # -# -program_name = 'etf2ly' -version = '@TOPLEVEL_VERSION@' -if version == '@' + 'TOPLEVEL_VERSION' + '@': - version = '(unknown version)' # uGUHGUHGHGUGH - + import __main__ import getopt import sys @@ -38,6 +33,12 @@ import re import string import os +program_name = sys.argv[0] + +version = '@TOPLEVEL_VERSION@' +if version == '@' + 'TOPLEVEL_VERSION' + '@': + version = '(unknown version)' # uGUHGUHGHGUGH + finale_clefs= ['treble', 'alto', 'tenor', 'bass', 'percussion', 'treble_8', 'bass_8', 'baritone'] def lily_clef (fin): @@ -75,27 +76,52 @@ def transpose(orig, delta): -# find transposition of C-major scale that belongs here. def interpret_finale_key_sig (finale_id): + """ +find the transposition of C-major scale that belongs here. + +we are not going to insert the correct major/minor, we only want to +have the correct number of accidentals +""" + p = (0,0) - if 0 <= finale_id < 7: - while finale_id > 0: + + + bank_number = finale_id >> 8 + accidental_bits = finale_id & 0xff + + if 0 <= accidental_bits < 7: + while accidental_bits > 0: p = transpose (p, (4,0)) # a fifth up - finale_id = finale_id - 1 - elif 248 < finale_id <= 255: - while finale_id < 256: + accidental_bits = accidental_bits - 1 + elif 248 < accidental_bits <= 255: + while accidental_bits < 256: p = transpose (p, (3,0)) - finale_id = finale_id + 1 + accidental_bits = accidental_bits + 1 + if bank_number == 1: + # minor scale + p = transpose (p, (5, 0)) p = (p[0] % 7, p[1]) - return p + + return KeySignature (p, bank_number) # should cache this. -def find_scale (transposition): +def find_scale (keysig): cscale = map (lambda x: (x,0), range (0,7)) - trscale = map(lambda x, k=transposition: transpose(x, k), cscale) - +# print "cscale: ", cscale + ascale = map (lambda x: (x,0), range (-2,5)) +# print "ascale: ", ascale + transposition = keysig.pitch + if keysig.sig_type == 1: + transposition = transpose(transposition, (2, -1)) + transposition = (transposition[0] % 7, transposition[1]) + trscale = map(lambda x, k=transposition: transpose(x, k), ascale) + else: + trscale = map(lambda x, k=transposition: transpose(x, k), cscale) +# print "trscale: ", trscale return trscale + def EDU_to_duration (edu): log = 1 d = 4096 @@ -111,7 +137,7 @@ def EDU_to_duration (edu): dots = 2 return (log, dots) -def rat_to_lily_duration (rat): +def rational_to_lily_skip (rat): (n,d) = rat basedur = 1 @@ -233,8 +259,9 @@ class Slur: if not cs or not ce: raise IndexError - cs.note_suffix = '(' + cs.note_suffix - ce.note_prefix = ce.note_prefix + ')' + cs.note_suffix = '-(' + cs.note_suffix + ce.note_suffix = ce.note_suffix + '-)' + except IndexError: sys.stderr.write ("""\nHuh? Slur no %d between (%d,%d), with %d notes""" % (self.number, startnote, endnote, len (chords))) @@ -243,7 +270,7 @@ class Global_measure: def __init__ (self, number): self.timesig = '' self.number = number - self.keysignature = None + self.key_signature = None self.scale = None self.force_break = 0 @@ -256,16 +283,22 @@ class Global_measure: def set_timesig (self, finale): (beats, fdur) = finale (log, dots) = EDU_to_duration (fdur) + + if dots == 1: + beats = beats * 3 + log = log * 2 + dots = 0 + if dots <> 0: - sys.stderr.write ("\nHuh? Beat duration has a dot? (EDU Duration = %d)" % fdur) + sys.stderr.write ("\nHuh? Beat duration has dots? (EDU Duration = %d)" % fdur) self.timesig = (beats, log) def length (self): return self.timesig - def set_keysig (self, finale): + def set_key_sig (self, finale): k = interpret_finale_key_sig (finale) - self.keysignature = k + self.key_signature = k self.scale = find_scale (k) def set_flags (self,flag1, flag2): @@ -362,10 +395,28 @@ class Verse: str = str + ' ' * 4 + line + '\n' line = '' - str = """\nverse%s = \\lyrics {\n %s}\n""" % (encodeint (self.number - 1) ,str) + str = """\nverse%s = \\lyricmode {\n %s }\n""" % (encodeint (self.number - 1) ,str) return str +class KeySignature: + def __init__(self, pitch, sig_type = 0): + self.pitch = pitch + self.sig_type = sig_type + + def signature_type (self): + if self.sig_type == 1: + return "\\minor" + else: + # really only for 0, but we only know about 0 and 1 + return "\\major" + def equal (self, other): + if other and other.pitch == self.pitch and other.sig_type == self.sig_type: + return 1 + else: + return 0 + + class Measure: def __init__(self, no): self.number = no @@ -412,14 +463,19 @@ class Frame: # do grace notes. lastch = None + in_grace = 0 for c in self.chords: if c.grace and (lastch == None or (not lastch.grace)): c.chord_prefix = r'\grace {' + c.chord_prefix + in_grace = 1 elif not c.grace and lastch and lastch.grace: lastch.chord_suffix = lastch.chord_suffix + ' } ' - + in_grace = 0 + lastch = c - + + if lastch and in_grace: + lastch.chord_suffix += '}' def dump (self): @@ -442,7 +498,7 @@ class Frame: 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 + rat_to_lily_duration (left) + str = str + rational_to_lily_skip (left) str = str + ' | \n' return str @@ -483,9 +539,12 @@ class Staff: e = '' if g: - if last_key <> g.keysignature: - e = e + "\\key %s \\major " % lily_notename (g.keysignature) - last_key = g.keysignature + 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 @@ -506,7 +565,7 @@ class Staff: str = string.join (map (lambda x: '(volta %s)' % x, strs)) - e = e + ' \\property Score.repeatCommands = #\'(%s) ' % str + e = e + ' \\set Score.repeatCommands = #\'(%s) ' % str if g.force_break: e = e + ' \\break ' @@ -516,7 +575,7 @@ class Staff: last_clef = m.clef if e: if gap <> (0,1): - k = k +' ' + rat_to_lily_duration (gap) + '\n' + k = k +' ' + rational_to_lily_skip (gap) + '\n' gap = (0,1) k = k + e @@ -525,7 +584,7 @@ class Staff: if 'stop' in g.repeats: k = k + ' \\bar ":|" ' - k = '%sglobal = \\notes { %s }\n\n ' % (self.staffid (), k) + k = '%sglobal = { %s }\n\n ' % (self.staffid (), k) return k def dump (self): @@ -552,7 +611,7 @@ class Staff: if fr: first_frame = fr if gap <> (0,1): - laystr = laystr +'} %s {\n ' % rat_to_lily_duration (gap) + laystr = laystr +'} %s {\n ' % rational_to_lily_skip (gap) gap = (0,1) laystr = laystr + fr.dump () else: @@ -564,7 +623,7 @@ class Staff: % (self.number, m.number)) if first_frame: l = self.layerid (x) - laystr = '%s = \\notes { { %s } }\n\n' % (l, laystr) + laystr = '%s = { { %s } }\n\n' % (l, laystr) str = str + laystr layerids.append (l) @@ -574,7 +633,7 @@ class Staff: stafdef = stafdef + ' \\' + i - str = str + '%s = \\context Staff = %s <\n %s\n >\n' % \ + str = str + '%s = \\context Staff = %s <<\n %s\n >>\n' % \ (self.staffid (), self.staffid (), stafdef) return str @@ -700,15 +759,18 @@ class Chord: if rest: nn = rest - s = s + '%s%d%s' % (nn, self.duration[0], '.'* self.duration[1]) + s = s + nn if not self.pitches: - s = 'r%d%s' % (self.duration[0] , '.'* self.duration[1]) - s = self.note_prefix + s + self.note_suffix + 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 @@ -757,7 +819,7 @@ Return: (value, rest-of-STR) return (string.atoi (dec), str) else: - sys.stderr.write ("Can't convert `%s'\n" % str) + sys.stderr.write ("can't convert `%s'\n" % str) return (None, str) @@ -934,7 +996,8 @@ class Etf_file: measno = indices[0] keynum = contents[1] meas =self. get_global_measure (measno) - meas.set_keysig (keynum) + + meas.set_key_sig (keynum) beats = contents[2] beatlen = contents[3] @@ -1068,7 +1131,8 @@ class Etf_file: sys.stderr.write ("\nLyrics found; edit to use \\addlyrics to couple to a staff\n") if staffs: - str = str + '\\score { < %s > } ' % string.join (staffs) + str += '\\version "2.3.25"\n' + str = str + '<<\n %s\n>> } ' % string.join (staffs) return str @@ -1088,22 +1152,25 @@ def identify(): sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) def help (): - sys.stdout.write("""Usage: etf2ly [OPTION]... ETF-FILE + sys.stdout.write("""Usage: etf2ly [OPTIONS]... ETF-FILE Convert ETF to LilyPond. Options: - -h,--help this help - -o,--output=FILE set output filename to FILE - -v,--version version information + -h, --help print this help + -o, --output=FILE set output filename to FILE + -v, --version show version information Enigma Transport Format is a format used by Coda Music Technology's Finale product. This program will convert a subset of ETF to a ready-to-use lilypond file. -Report bugs to bug-gnu-music@gnu.org +Report bugs via + + http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs + +Written by Han-Wen Nienhuys . -Written by Han-Wen Nienhuys """) def print_version (): @@ -1113,7 +1180,7 @@ This is free software. It is covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Invoke as `midi2ly --warranty' for more information. -Copyright (c) 2000 by Han-Wen Nienhuys +Copyright (c) 2000--2006 by Han-Wen Nienhuys """ % version)