-
Notifications
You must be signed in to change notification settings - Fork 19
/
mid2loop.py
executable file
·53 lines (42 loc) · 1.37 KB
/
mid2loop.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python3
import mido
import sys
from looper import Loop, Note
# Syntax: mid2loop <foo.mid> <row> <col> <bars_to_loop>
midi_file = mido.MidiFile(filename=sys.argv[1])
cell = sys.argv[2:4]
bars = int(sys.argv[4])
loop = Loop(looper=None, cell=cell)
loop.notes.clear()
loop.channel = 3
def quantize(t, q):
return q*round(t/q)
def time2tick(t):
return quantize(24 * t / tempo * 1000000, 6)
now = 0
tempo = 0 # microseconds per quarter note
notes = {} # note -> start_time
for message in midi_file:
now += message.time
if message.type == "time_signature":
print("# time signature: {}/{}".format(message.numerator, message.denominator))
loop.teach_interval = bars * 24 * message.numerator
if message.type == "set_tempo":
tempo = message.tempo
if message.type == "note_on" and message.velocity > 0:
notes[message.note] = now
elif message.type in ("note_on", "note_off"):
start_time = notes.pop(message.note, None)
if start_time is None:
print("# unmatched note: {}".format(message.note))
else:
duration = now - start_time
start_tick = time2tick(start_time)
duration_tick = time2tick(duration)
print(message.note, start_tick, duration_tick)
if start_tick not in loop.notes:
loop.notes[start_tick] = []
loop.notes[start_tick].append(Note(message.note, 108, duration_tick))
from persistence import cache
for db in cache.values():
db.close()