3 # once upon a rainy monday afternoon.
8 # ABC standard v1.6: http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt
11 program_name = 'abc-to-ly'
12 version = '@TOPLEVEL_VERSION@'
21 sys.stderr.write ("This script needs Python 1.5.1\n")
28 global_voice_stuff = []
30 global_key = [0] * 7 # UGH
31 names = ["One", "Two", "Three"]
41 def __init__ (self, n, d = 1):
46 g = gcd (self.num, self.den)
47 self.num = self.num / g
48 self.den = self.den /g
53 def __sub__ (self, other):
58 print ("global = \\notes{")
59 for i in global_voice_stuff:
64 def dump_header (hdr):
67 print '%s = "%s";\n'% (k,hdr[k])
71 for i in range (len (lyrics)):
72 print ("verse%s = \\lyrics {" % names [i])
77 for i in range (len (voices)):
78 print ("voice%s = \\notes {" % names [i])
87 for i in range (len (voices)):
88 print (" \\context Staff=%s \\voice%s" %
89 (names [i], names [i]))
90 for i in range (len (lyrics)):
94 print (" \\context Lyrics=%s \\addlyrics \\voice%s \\verse%s" %
95 (names [i], names [j], names [i]))
98 #print "%%%s" % global_voice_stuff, 1
101 def set_default_length (s):
102 m = re.search ('1/([0-9]+)', s)
104 __main__.default_len = string.atoi ( m.group (1))
113 sys.stderr.write ("can't open file: %s\n" % f)
117 sys.stderr.write ("gulped emty file: %s\n" % f)
122 # pitch manipulation. Tuples are (name, alteration).
123 # 0 is (central) C. Alteration -1 is a flat, Alteration +1 is a sharp
124 # pitch in semitones.
125 def semitone_pitch (tup):
135 p = p + t* 2 + tup[1]
138 def fifth_above_pitch (tup):
139 (n, a) = (tup[0] + 4, tup[1])
141 difference = 7 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
152 (t,a) = fifth_above_pitch (p)
153 if semitone_pitch((t,a)) % 12 == 0:
165 (t,a) = quart_above_pitch (p)
166 if semitone_pitch((t,a)) % 12 == 0:
172 def quart_above_pitch (tup):
173 (n, a) = (tup[0] + 3, tup[1])
175 difference = 5 - (semitone_pitch ((n,a)) - semitone_pitch (tup))
183 intkey = (ord (k[0]) - ord('a') + 5) % 7
187 if k and k[0] == 'b':
190 elif k and k[0] == '#':
194 keytup = (intkey, intkeyacc)
196 sharp_key_seq = sharp_keys ()
197 flat_key_seq = flat_keys ()
201 if keytup in sharp_key_seq:
203 key_count = sharp_key_seq.index (keytup)
204 accseq = map (lambda x: (4*x -1 ) % 7, range (1, key_count + 1))
206 elif keytup in flat_key_seq:
208 key_count = flat_key_seq.index (keytup)
209 accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1))
215 key_table[a] = key_table[a] + accsign
228 def try_parse_tuplet_begin (str, state):
229 if str and str[0] in DIGITS:
232 state.parsing_tuplet = 1
234 voices_append ("\\times %s {" % tup_lookup[dig])
237 def try_parse_group_end (str, state):
238 if str and str[0] in HSPACE:
240 if state.parsing_tuplet:
241 state.parsing_tuplet = 0
245 def header_append (key, a):
247 if header.has_key (key):
248 s = header[key] + "\n"
251 def lyrics_append (a):
255 if len (lyrics) <= i:
257 lyrics [i] = lyrics [i] + a + "\n"
259 def voices_append (a):
263 if len (voices) <= i:
265 voices [i] = voices [i] + a + "\n"
267 def try_parse_header_line (ln):
268 m = re.match ('^(.): *(.*)$', ln)
273 a = re.sub ('"', '\\"', a)
279 global_voice_stuff.append ('\\time %s;' % a)
281 __main__.global_key =compute_key (a)# ugh.
283 global_voice_stuff.append ('\\key %s;' % a)
285 header ['origin'] = a
287 header ['crossRefNumber'] = a
291 header_append ('history', a)
295 header ['subtitle'] = a
297 set_default_length (ln)
305 def pitch_to_mudela_name (name, acc):
315 return chr (name + ord('c')) + s * acc
317 def octave_to_mudela_quotes (o):
330 while str and str[0] in DIGITS:
331 durstr = durstr + str[0]
336 n =string.atoi (durstr)
340 def duration_to_mudela_duration (multiply_tup, defaultlen, dots):
343 # (num / den) / defaultlen < 1/base
344 while base * multiply_tup[0] < defaultlen * multiply_tup[1]:
348 return '%d%s' % ( base, '.'* dots)
354 self.parsing_tuplet = 0
357 # WAT IS ABC EEN ONTZETTENDE PROGRAMMEERPOEP !
358 def try_parse_note (str, parser_state):
381 if str[0] in "ABCDEFG":
382 str = string.lower (str[0]) + str[1:]
387 if str[0] in "abcdefg":
388 notename = (ord(str[0]) - ord('a') + 5)%7
391 return str # failed; not a note!
396 while str[0] == '\'':
401 den = parser_state.next_den
402 parser_state.next_den = 1
404 (str, num) = parse_num (str)
413 (str, d) =parse_num (str)
417 current_dots = parser_state.next_dots
418 parser_state.next_dots = 0
421 current_dots = current_dots + 1;
422 parser_state.next_den = parser_state.next_den * 2
427 parser_state.next_dots = parser_state.next_dots + 1
431 voices_append ("%s%s%s" %
432 (pitch_to_mudela_name (notename, acc + global_key[notename]),
433 octave_to_mudela_quotes (octave),
434 duration_to_mudela_duration ((num,den), default_len, current_dots)))
443 def junk_space (str):
444 while str and str[0] in '\t\n ':
450 def try_parse_guitar_chord (str):
451 if str and str[0] == '"':
454 while str and str[0] != '"':
461 sys.stderr.write ("warning: ignoring guitar chord: %s\n" % gc)
465 def try_parse_escape (str):
466 if not str or str [0] != '\\':
470 if str and str[0] == 'K':
471 key_table = compute_key ()
476 # |] thin-thick double bar line
477 # || thin-thin double bar line
478 # [| thick-thin double bar line
481 # :: left-right repeat
484 def try_parse_bar (str):
485 if str and str[0] == '|':
494 sys.stderr.write ("warning: repeat kludge\n")
497 voices_append ('\\bar "%s";' % bs)
500 if str and str[:2] == '[|':
501 sys.stderr.write ("warning: thick-thin bar kludge\n")
502 voices_append ('\\bar "||";')
505 if str and str[:2] == ':|':
506 sys.stderr.write ("warning: repeat kludge\n")
507 voices_append ('\\bar ":|:";')
510 if str and str[:2] == '::':
511 sys.stderr.write ("warning: repeat kludge\n")
512 voices_append ('\\bar ":|:";')
518 def try_parse_chord_delims (str):
519 if str and str[0] == '[':
523 if str and str[0] == ']':
529 def try_parse_grace_delims (str):
530 if str and str[0] == '{':
532 voices_append ('\\grace { ')
534 if str and str[0] == '}':
540 # Try nibbling characters off until the line doesn't change.
541 def try_parse_body_line (ln, state):
545 ln = try_parse_chord_delims (ln)
546 ln = try_parse_note (ln, state)
547 ln = try_parse_bar (ln)
548 ln = try_parse_escape (ln)
549 ln = try_parse_guitar_chord (ln)
550 ln = try_parse_tuplet_begin (ln, state)
551 ln = try_parse_group_end (ln, state)
552 ln = try_parse_grace_delims (ln)
556 sys.stderr.write ("Huh? Don't understand `%s'\n" % ln)
565 state = Parser_state ()
567 if re.match ('^[\t ]*(%.*)?$', l):
571 m = try_parse_header_line (l)
576 m = try_parse_body_line (l,state)
580 sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version))
584 This is a disfunctional ABC to mudela convertor. It only gulps input, and
585 says huh when confused. Go ahead and fix me.
587 Usage: abc-2-ly INPUTFILE
589 -h, --help this help.
595 (options, files) = getopt.getopt (sys.argv[1:], 'h', ['help'])
600 if o== '--help' or o == '-h':