- commit
- bdda87bc720b6ca7dc59d3f1efd4e6fe039d1220
- parent
- 6d83259c70a6c4edb05ea7d1b6978cd271394e00
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2023-09-18 21:37
refactor midi
Diffstat
| M | iparser.py | 12 | +++++------- |
| M | midi.py | 86 | ++++++++++++++++++++++++------------------------------------- |
| M | xi2.py | 23 | ++++++++++------------- |
3 files changed, 48 insertions, 73 deletions
diff --git a/iparser.py b/iparser.py
@@ -1,5 +1,4 @@1 -1 from midi import Midi2 -1 from midi import MidiFile-1 1 import midi 3 2 4 3 # The tricky part here is the time conversion. 5 4 # and noteOff events @@ -9,7 +8,7 @@ class IParser: 9 8 """Convert intermediate code to MIDI bytecode.""" 10 9 11 10 def __init__(self, seq, ch=0, offset=60):12 -1 self.midi = Midi()-1 11 self.midi = midi.Midi() 13 12 self.ch = ch 14 13 self.offset = offset 15 14 self.dt = 0 @@ -94,8 +93,7 @@ class IParser: 94 93 95 94 if __name__ == '__main__': 96 95 a = [(('0', '1'), '2'), '4', '5', '-', '', ['0', '4', '7'], '', '', '0', ['3', '-']]97 -198 -1 f = MidiFile()99 96 ip = IParser(a, 0, 60)100 -1 f.add_track(ip.midi)101 -1 f.write('test.mid')-1 97 -1 98 with open('test.mid', 'wb') as fh: -1 99 midi.write_file(fh, [ip.midi])
diff --git a/midi.py b/midi.py
@@ -1,44 +1,35 @@ 1 1 # http://www.sonicspot.com/guide/midifiles.html 2 2 -1 3 import io -1 4 3 5 TIME_DEVISION = 0x00c0 # two bytes 4 6 5 7 6 8 class Midi: 7 9 """Create MIDI bytecode from MIDI events.""" 8 109 -1 def __init__(self):10 -1 self._buf = ''11 -112 -1 def __str__(self):13 -1 return self._buf.encode('hex')14 -115 -1 def __add__(self, other):16 -1 m = Midi()17 -1 m._buf = self._buf + other._buf18 -1 return m19 -120 -1 def write(self, name):21 -1 f = open(name, 'w')22 -1 f.write(self._buf)23 -1 f.close()-1 11 def __init__(self, fh=None): -1 12 if fh: -1 13 self.fh = fh -1 14 else: -1 15 self.fh = io.BytesIO() 24 16 25 17 def write_fixed(self, value, size):26 -1 if type(value) == type(''):27 -1 self._buf += (' ' * size + value)[-size:]28 -1 else:29 -1 if size != 0:30 -1 self.write_fixed(value / 0x100, size - 1)31 -1 self._buf += chr(value % 0x100)-1 18 if isinstance(value, bytes): -1 19 self.fh.write((b' ' * size + value)[-size:]) -1 20 elif size != 0: -1 21 assert isinstance(value, int) -1 22 self.write_fixed(value >> 8, size - 1) -1 23 self.fh.write(bytes([value & 0xff])) 32 24 33 25 def write_variable(self, value, _rec=False):34 -1 # b = bin(a)[2:]; eval('0b'+''.join([b[k*8:(k+1)*8][1:] for k in range(int(len(b)/8))]))35 26 if value == 0 and _rec: 36 27 return 037 -1 self.write_variable(value / 0x80, True)-1 28 self.write_variable(value >> 7, True) 38 29 if _rec:39 -1 self._buf += chr(value % 0x80 + 0x80)-1 30 self.fh.write(bytes([(value & 0x7f) | 0x80])) 40 31 else:41 -1 self._buf += chr(value % 0x80)-1 32 self.fh.write(bytes([value & 0x7f])) 42 33 43 34 def ch_event(self, dt, event, ch, p1, p2=-1): 44 35 self.write_variable(int(dt * TIME_DEVISION)) @@ -54,7 +45,7 @@ class Midi: 54 45 self.write_variable(length) 55 46 self.write_fixed(data, length) 56 4757 -1 def sys_ex(self, dt, length, data):-1 48 def system_exclusive(self, dt, length, data): 58 49 self.write_variable(int(dt * TIME_DEVISION)) 59 50 self.write_fixed(0xf0, 1) 60 51 self.write_variable(length) @@ -84,34 +75,23 @@ class Midi: 84 75 self.ctrl_event(dt, ch, 0x07, int(vol * 0x7f)) 85 76 86 7787 -1 class MidiFile(Midi):88 -1 def __init__(self):89 -1 Midi.__init__(self)90 -1 self._tracks = []91 -192 -1 def update(self):93 -1 self._buf = ''94 -1 self.write_fixed(0x4D546864, 4) # chunk ID "MThd"95 -1 self.write_fixed(6, 4) # chunk size96 -1 self.write_fixed(1, 2) # format type97 -1 self.write_fixed(len(self._tracks), 2) # numer of tracks98 -1 self.write_fixed(TIME_DEVISION, 2) # time devision99 -1 for track in self._tracks:100 -1 self.write_fixed(0x4D54726B, 4) # chunk ID "MTtr"101 -1 self.write_fixed(len(track._buf) + 4, 4) # chunk size102 -1 self._buf += track._buf103 -1 self.meta_event(0, 0x2f, 0, '') # end_track event104 -1105 -1 def add_track(self, data, update=True):106 -1 self._tracks.append(data)107 -1 if update:108 -1 self.update()-1 78 def write_file(fh, tracks): -1 79 f = Midi(fh) -1 80 f.write_fixed(0x4D546864, 4) # chunk ID "MThd" -1 81 f.write_fixed(6, 4) # chunk size -1 82 f.write_fixed(1, 2) # format type -1 83 f.write_fixed(len(tracks), 2) # numer of tracks -1 84 f.write_fixed(TIME_DEVISION, 2) # time devision -1 85 for track in tracks: -1 86 f.write_fixed(0x4D54726B, 4) # chunk ID "MTtr" -1 87 buf = track.fh.getvalue() -1 88 f.write_fixed(len(buf) + 4, 4) # chunk size -1 89 f.fh.write(buf) -1 90 f.meta_event(0, 0x2f, 0, b'') # end_track event 109 91 110 92 111 93 if __name__ == '__main__': 112 94 # Example:113 -1 f = MidiFile()114 -1 f.add_track(Midi())115 95 t = Midi() 116 96 t.set_vol(0, 1, 1) 117 97 t.ctrl_event(0, 1, 0x00, 0) # setting bank @@ -121,6 +101,6 @@ if __name__ == '__main__': 121 101 t.note_off(1, 1, 62) 122 102 t.note_on(0, 1, 64) 123 103 t.note_off(1, 1, 64)124 -1 f.add_track(t)125 -1 print(f)126 -1 f.write('test.mid')-1 104 -1 105 with open('test.mid', 'wb') as fh: -1 106 write_file(fh, [t])
diff --git a/xi2.py b/xi2.py
@@ -1,9 +1,8 @@ 1 1 import argparse 2 2 import re 3 3 -1 4 import midi 4 5 from iparser import IParser5 -1 from midi import Midi6 -1 from midi import MidiFile7 6 8 7 """Parse xi2 code and convert to MIDI.""" 9 8 @@ -103,17 +102,15 @@ for s in ll.split('\n\n'): 103 102 for name, data in tracks.items(): 104 103 data += [''] * (l - len(data)) 105 104106 -1 # create midi107 -1 mf = MidiFile()108 -1109 105 # create first track with meta infos110 -1 m = Midi()111 -1 m.set_tempo(args.tempo)112 -1 mf.add_track(m)-1 106 midi_tracks = [] -1 107 t0 = midi.Midi() -1 108 t0.set_tempo(args.tempo) -1 109 midi_tracks.append(t0) 113 110 114 111 ch = 0115 -1 for name, track in tracks.iteritems():116 -1 m = Midi()-1 112 for name, track in tracks.items(): -1 113 m = midi.Midi() 117 114 # write meta info 118 115 m.meta_event(0, 0x04, len(name), name) 119 116 try: @@ -125,8 +122,8 @@ for name, track in tracks.iteritems(): 125 122 ip = IParser(track, ch=ch, offset=args.offset) 126 123 m += ip.midi 127 124 # write128 -1 mf.add_track(m)-1 125 midi_tracks.append(m) 129 126 ch += 1 130 127131 -1 # write to file132 -1 mf.write(args.outfile)-1 128 with open(args.outfile, 'wb') as fh: -1 129 midi.write_file(fh, midi_tracks)