-
Notifications
You must be signed in to change notification settings - Fork 0
/
midi.py
executable file
·67 lines (62 loc) · 1.93 KB
/
midi.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env python3
import sys
import os
import time
import mido
import struct
import array
Envelope = struct.Struct("iidixxxx")
def make_instrument(channel: int, amps: "List[float]") -> bytes:
return b"\xF0" + \
struct.pack("B", ((len(amps) << 4) | (channel & 15))) + \
array.array("d", amps).tobytes() + \
b"\xF1" + \
struct.pack("B", channel & 15) + \
Envelope.pack(4410, 44100, 0.3, 10000)
def playnote(note, amp):
if amp != 0:
sys.stdout.buffer.write(bytes([0, note, amp]))
else:
sys.stdout.buffer.write(bytes([1, note]))
sys.stdout.buffer.flush()
if sys.argv[1] == "--loop":
loop = True
file = mido.MidiFile(sys.argv[2])
else:
loop = False
file = mido.MidiFile(sys.argv[1])
sys.stderr.write("%.2f seconds\n" % file.length)
play = file.play()
while True:
try:
for msg in play if not loop else file.play():
#sys.stderr.write(str(msg.bytes()))
if msg.type in ('note_on', 'note_off', 'pitchwheel'):
sys.stdout.buffer.write(bytes(msg.bytes()))
elif msg.type == 'program_change':
sys.stdout.buffer.write(bytes(msg.bytes()))
# if msg.program > 1:
# sys.stdout.buffer.write(bytes(msg.bytes()))
# else:
# amps = [1.0, 0, 1/4, 0, 1/9, 0, 1/16, 0, 1/49]
# sys.stdout.buffer.write(make_instrument(msg.channel, amps))
sys.stdout.buffer.flush()
break
except KeyboardInterrupt:
#sys.stdout.close()
#https://docs.python.org/3/faq/library.html#why-doesn-t-closing-sys-stdout-stdin-stderr-really-close-it
exit()
exit()
"""
for msg in mido.MidiFile(sys.argv[1]).play():
#sys.stderr.write(str(msg.bytes()))
if msg.type == 'note_on' and msg.velocity > 0:
sys.stdout.buffer.write(bytes(msg.bytes()))
elif msg.type == 'note_off':
sys.stdout.buffer.write(bytes(msg.bytes()))
elif msg.type == 'note_on' and msg.velocity == 0:
sys.stdout.buffer.write(bytes([0x80+msg.channel, msg.note, 0]))
elif msg.type == 'program_change':
sys.stdout.buffer.write(bytes(msg.bytes()))
sys.stdout.buffer.flush()
"""