#!@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
#
# * 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
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):
-# 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
dots = 2
return (log, dots)
-def rat_to_lily_duration (rat):
+def rational_to_lily_skip (rat):
(n,d) = rat
basedur = 1
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)))
def __init__ (self, number):
self.timesig = ''
self.number = number
- self.keysignature = None
+ self.key_signature = None
self.scale = None
self.force_break = 0
def set_timesig (self, finale):
(beats, fdur) = finale
(log, dots) = EDU_to_duration (fdur)
- assert dots == 0
+
+ if dots == 1:
+ beats = beats * 3
+ log = log * 2
+ dots = 0
+
+ if dots <> 0:
+ 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):
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
# 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):
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
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
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 '
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
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):
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:
% (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)
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
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
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]
frame_obj_list = [None]
for frno in m.frames:
- fr = self.frames[frno]
- frame_obj_list.append (fr)
+ try:
+ fr = self.frames[frno]
+ frame_obj_list.append (fr)
+ except IndexError:
+ sys.stderr.write ("\nNon-existent frame %d" % frno)
m.frames = frame_obj_list
for fr in frame_obj_list[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)
+ str += '\\version "2.3.25"\n'
+ str = str + '<<\n %s\n>> } ' % string.join (staffs)
return str
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 to bug-lilypond@gnu.org.
+
+Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>.
-Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>
""")
def print_version ():
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 <hanwen@cs.uu.nl>
+Copyright (c) 2000--2005 by Han-Wen Nienhuys <hanwen@cs.uu.nl>
""" % version)