VocalEasel/mma/util/mup2mma.py

257 lines
6.0 KiB
Python
Raw Normal View History

2007-04-29 06:47:40 +00:00
#!/usr/bin/env python
""" mup2mma extracts chords from a MUP music notation file and
creates a MMA file. For this to work the MUP file must use
the macro "C" for chord. In my MUP files I have the following:
define C bold (11) chord above all: @
This script just checks all input lines and assumes that anything
starting with "C" is a chord line.
Additional "features":
Lines in the form "// TEMPO: xx" generate a Tempo entry
"time =" lines are parsed for common time signatures
repeats are inserted as comment lines
0.3 - added options:
-m add melody lines
-l add lyrics
-o overwrite
0.4 - reformatted output
0.5 - corrected melody/lyric notation.
bvdp, Dec/2004
"""
import os
import sys
import commands
import getopt
# Useful functions
def error(m=''):
print "Error: %s" % m
sys.exit(1)
def usage():
print "mup2mma - (c) Bob van der Poel"
print "Extract MMA data from MUP file."
print "Options:"
print " -o overwrite existing MMA file"
print " -m extract melody data"
print " -l extract lyric data"
print " -v print version"
sys.exit(0)
# Global variables
Version = '0.5'
overwrite = 0 # set if overwrite of old mma file okay
doLyric = 0 # set if we want lyrics output
doMelody = 0 # set if we want melody output
# Parse command line, open files
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "omlv")
except getopt.GetoptError:
usage()
for o,a in opts:
if o == '-o':
overwrite = 1
elif o == '-l':
doLyric = 1
elif o == '-m':
doMelody = 1
elif o == '-v':
print Version
sys.exit(0)
else:
usage()
if len(args) != 1:
error("Exactly 1 filename is required.")
infile = args[0]
outfile = os.path.basename(infile)
if outfile.endswith('.mup'):
outfile=outfile[:-4]
title=outfile.replace("-", ' ').title()
outfile += ".mma"
try:
bars = file(infile)
except:
error("Can't open input file '%s'." % infile)
if os.path.exists(outfile) and not overwrite:
error("File '%s' already exists." % outfile)
try:
out=file(outfile, "w")
except:
error("Can't open output file '%s'." % outfile)
# Input and output files open, start processing
out.write( "// %s\n\n" % title)
bnum = 1
donebar = 0
melody = ''
lyric = ''
chordList=[]
for b in bars:
b=b.strip()
if b=='': # skip empty lines
continue
if b.startswith("// TEMPO:"):
out.write("Tempo %s\n\n" % b.split()[2])
continue
# Parse out time sig from MUP
ck = b.split("=")
if len(ck) and ck[0].strip() == 'time':
ts=ck[1].strip()
if ts in ('common', '4/4'):
beats = 4
posStep = 1
elif ts in ('cut', '2/4', '2/2'):
beats = 2
posStep = .5
elif ts=='3/4':
beats = 3
posStep = 1
elif ts=='6/8':
beats = 6
posStep = 1
elif ts=='12/8':
beats = 12
posStep = 1
else:
error("Uknown time sig, %s" % b)
# Parse line number from MUP
if b.startswith('// #') or b.startswith('//# '):
bnum = b[4:]
# Parse out melody, lyric and chords.
# Melody must be a line starting with "M:"
# Lyric must be a line starting with "L:"
# Chord must be a line starting with "C "
key = b.split()[0]
if key == 'M:' and doMelody:
melody = b.split(' ', 1)[1]
elif key == 'L:' and doLyric:
lyric = b.split(' ', 1)[1]
elif key == 'C':
ch = b[2:]
ch=ch.replace ('"', ' ')
ch=ch.replace('&', 'b')
ch = ch[:-1]
ch=ch.split(';')
chordList = []
pos = 1.0
for c in ch:
c = c.split()
off = c[0]
# Strip out printing offset from chord. Since the position
# has been split off, we just strip out everything after the
# inital '['. If this doesn't work, then the MUP is wrong as well
# eg: 1.5[-5] becomes 1.5
if off.count('['):
off=off[:off.index('[')]
count = float(off)
while pos < count:
chordList.append('/')
pos += posStep
chord=c[1]
if chord.upper()=="TACET" or chord.upper()=='N.C':
chord = 'z'
chord = chord.replace('^', 'M')
chord = chord.replace('o', 'dim')
chord = chord.replace('\\(dim)', 'dim')
chordList.append(chord )
pos += posStep
elif key in ('bar', 'repeatend', 'endbar', 'dblbar', '(dblbar)',
'repeatstart', 'repeatboth' ):
out.write('%-4s' % bnum)
if not chordList:
chordList = ['/']
for a in chordList:
out.write((' %6s' % a).rstrip())
chordList = []
if doMelody and melody:
out.write((' { %s }' % melody).rstrip())
melody = ''
if doLyric and lyric:
out.write((' [ %s ]' % lyric).rstrip())
lyric = ''
out.write('\n')
if key == 'repeatend':
out.write( "\n// RepeatEnd\n\n")
if key == 'repeatboth':
out.write( "\n// RepeatEnd\n\n")
out.write( "// Repeat\n\n")
if key == "repeatstart" or key=='(dblbar)':
out.write( "\n// Repeat\n\n")
rpt = b.split()[1:]
if len(rpt) and rpt[0] == "ending":
out.write( '\n// RepeatEnding\n\n')
else:
pass # Just ignore other MUP stuff
out.write('\n')
out.close()