- commit
- 4899d3cf474c0667c0405b60e13f16a4be74f898
- parent
- 3a3ddbdabfb471b1ba7740d38b5952a6a7f93c4c
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2023-09-19 06:41
style: high level restructure of xi2
Diffstat
| M | xi2.py | 193 | ++++++++++++++++++++++++++++++++----------------------------- |
1 files changed, 100 insertions, 93 deletions
diff --git a/xi2.py b/xi2.py
@@ -1,61 +1,17 @@ -1 1 """Parse xi2 code and convert to MIDI.""" -1 2 1 3 import argparse 2 4 import re 3 5 4 6 import midi 5 7 from iparser import IParser 6 87 -1 """Parse xi2 code and convert to MIDI."""8 -19 -1 parser = argparse.ArgumentParser()10 -1 parser.add_argument('-t', '--tempo', help="tempo in bpm", default=120, type=int)11 -1 parser.add_argument('-o', '--offset', help="key offset", default=60, type=int)12 -1 parser.add_argument('infile')13 -1 parser.add_argument('outfile')14 -1 args = parser.parse_args()15 9 16 10 def length(data): 17 11 data = re.sub('{[^}]*}', '', data) 18 12 data = re.sub('\([^\)]*\)', '', data) 19 13 return len(data.split(',')) - 1 20 1421 -1 f = open(args.infile)22 -1 lines = f.readlines()23 -1 f.close()24 -125 -1 ll = ''.join(lines)26 -1 # remove whitespace27 -1 ll = re.sub('[ \t]', '', ll)28 -1 # remove c++ style comments29 -1 # we have to escape linebreaks30 -1 ll = re.sub('\n', '\\\\n', ll)31 -1 ll = re.sub('/\*[^(\*)]*\*/', '', ll)32 -1 ll = re.sub('\\\\n', '\n', ll)33 -1 # remove c style comments34 -1 ll = re.sub('//[^\n]*\n', '', ll)35 -136 -1 # expand macros37 -1 ll = re.sub('\n', '\\\\n', ll)38 -1 while re.search('(\[[^\]]*\]):(.*)', ll):39 -1 match = re.search('(\[[^\]]*\]):(.*)', ll)40 -1 (key, after) = match.groups()41 -1 if after.startswith('<<'):42 -1 eol = after.split('\\n',1)[0][2:]43 -1 val = after.split(eol,2)[1]44 -1 ll = re.sub(re.escape("%s:<<%s%s%s" % (key, eol, val, eol)), '', ll)45 -1 else:46 -1 val = after.split('\\n',1)[0]47 -1 ll = re.sub(re.escape("%s:%s" % (key, val)), '', ll)48 -1 ll = re.sub(re.escape(key), val, ll)49 -1 ll = re.sub('\\\\n', '\n', ll)50 -151 -1 # remove trailing newlines52 -1 ll = re.sub('^\n*', '', ll)53 -1 # remove \n\n+54 -1 ll = re.sub('\n', '\\\\n', ll)55 -1 ll = re.sub('\\\\n(\\\\n)+', '\\\\n\\\\n', ll)56 -1 ll = re.sub('\\\\n', '\n', ll)57 -1 # remove newlines at the end58 -1 ll = re.sub('\n*$', '', ll)59 15 60 16 def parse(t): 61 17 string = '' @@ -78,51 +34,102 @@ def parse(t): 78 34 string += c 79 35 return stack[0] 80 3681 -1 # join track parts from different sets82 -1 tracks = dict()83 -1 for s in ll.split('\n\n'):84 -1 if len(tracks) == 0:85 -1 l = 086 -1 else:87 -1 l = max([len(t) for t in tracks])88 -1 for track in s.split('\n'):-1 37 -1 38 def parse_args(): -1 39 parser = argparse.ArgumentParser() -1 40 parser.add_argument('-t', '--tempo', help='tempo in bpm', default=120, type=int) -1 41 parser.add_argument('-o', '--offset', help='key offset', default=60, type=int) -1 42 parser.add_argument('infile') -1 43 parser.add_argument('outfile') -1 44 return parser.parse_args() -1 45 -1 46 -1 47 if __name__ == '__main__': -1 48 args = parse_args() -1 49 -1 50 with open(args.infile) as fh: -1 51 lines = fh.readlines() -1 52 -1 53 ll = ''.join(lines) -1 54 # remove whitespace -1 55 ll = re.sub('[ \t]', '', ll) -1 56 # remove c++ style comments -1 57 # we have to escape linebreaks -1 58 ll = re.sub('\n', '\\\\n', ll) -1 59 ll = re.sub('/\*[^(\*)]*\*/', '', ll) -1 60 ll = re.sub('\\\\n', '\n', ll) -1 61 # remove c style comments -1 62 ll = re.sub('//[^\n]*\n', '', ll) -1 63 -1 64 # expand macros -1 65 ll = re.sub('\n', '\\\\n', ll) -1 66 while re.search('(\[[^\]]*\]):(.*)', ll): -1 67 match = re.search('(\[[^\]]*\]):(.*)', ll) -1 68 (key, after) = match.groups() -1 69 if after.startswith('<<'): -1 70 eol = after.split('\\n',1)[0][2:] -1 71 val = after.split(eol,2)[1] -1 72 ll = re.sub(re.escape("%s:<<%s%s%s" % (key, eol, val, eol)), '', ll) -1 73 else: -1 74 val = after.split('\\n',1)[0] -1 75 ll = re.sub(re.escape("%s:%s" % (key, val)), '', ll) -1 76 ll = re.sub(re.escape(key), val, ll) -1 77 ll = re.sub('\\\\n', '\n', ll) -1 78 -1 79 # remove trailing newlines -1 80 ll = re.sub('^\n*', '', ll) -1 81 # remove \n\n+ -1 82 ll = re.sub('\n', '\\\\n', ll) -1 83 ll = re.sub('\\\\n(\\\\n)+', '\\\\n\\\\n', ll) -1 84 ll = re.sub('\\\\n', '\n', ll) -1 85 # remove newlines at the end -1 86 ll = re.sub('\n*$', '', ll) -1 87 -1 88 # join track parts from different sets -1 89 tracks = dict() -1 90 for s in ll.split('\n\n'): -1 91 if len(tracks) == 0: -1 92 l = 0 -1 93 else: -1 94 l = max([len(t) for t in tracks]) -1 95 for track in s.split('\n'): -1 96 try: -1 97 (name, data) = track.split(':', 1) -1 98 except Exception as e: -1 99 print(track) -1 100 raise e -1 101 data = parse(data) -1 102 if name not in tracks: -1 103 tracks[name] = [''] * l -1 104 tracks[name] += data -1 105 if len(tracks) == 0: -1 106 l = 0 -1 107 else: -1 108 l = max([len(t) for t in tracks]) -1 109 for name, data in tracks.items(): -1 110 data += [''] * (l - len(data)) -1 111 -1 112 # create first track with meta infos -1 113 midi_tracks = [] -1 114 t0 = midi.Midi() -1 115 t0.set_tempo(args.tempo) -1 116 midi_tracks.append(t0) -1 117 -1 118 ch = 0 -1 119 for name, track in tracks.items(): -1 120 m = midi.Midi() -1 121 # write meta info -1 122 m.meta_event_str(0, 0x04, name) 89 123 try:90 -1 (name, data) = track.split(':', 1)91 -1 except Exception as e:92 -1 print(track)93 -1 raise e94 -1 data = parse(data)95 -1 if name not in tracks:96 -1 tracks[name] = [''] * l97 -1 tracks[name] += data98 -1 if len(tracks) == 0:99 -1 l = 0100 -1 else:101 -1 l = max([len(t) for t in tracks])102 -1 for name, data in tracks.items():103 -1 data += [''] * (l - len(data))104 -1105 -1 # create first track with meta infos106 -1 midi_tracks = []107 -1 t0 = midi.Midi()108 -1 t0.set_tempo(args.tempo)109 -1 midi_tracks.append(t0)110 -1111 -1 ch = 0112 -1 for name, track in tracks.items():113 -1 m = midi.Midi()114 -1 # write meta info115 -1 m.meta_event_str(0, 0x04, name)116 -1 try:117 -1 prog = int(name)118 -1 except ValueError:119 -1 prog = 0120 -1 m.prog_ch(0, ch, prog)121 -1 # write data122 -1 IParser(m, track, ch=ch, offset=args.offset)123 -1 # write124 -1 midi_tracks.append(m)125 -1 ch += 1126 -1127 -1 with open(args.outfile, 'wb') as fh:128 -1 midi.write_file(fh, midi_tracks)-1 124 prog = int(name) -1 125 except ValueError: -1 126 prog = 0 -1 127 m.prog_ch(0, ch, prog) -1 128 # write data -1 129 IParser(m, track, ch=ch, offset=args.offset) -1 130 # write -1 131 midi_tracks.append(m) -1 132 ch += 1 -1 133 -1 134 with open(args.outfile, 'wb') as fh: -1 135 midi.write_file(fh, midi_tracks)