#!/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()