Skip to content

Instantly share code, notes, and snippets.

@miettal
Created July 3, 2014 11:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miettal/2c8c7630413959f477af to your computer and use it in GitHub Desktop.
Save miettal/2c8c7630413959f477af to your computer and use it in GitHub Desktop.
midi_test2.py
#!/usr/bin/env python
# coding:utf-8
#
# midi_test.py
#
# Author: Hiromasa Ihara (miettal)
# URL: http://miettal.com
# License: MIT License
# Created: 2014-06-05
import subprocess
import time
def midi_play(filename, callback) :
with open(filename) as f :
data = map(ord, f.read())
header = data[:4+4+6]
format_ = (header[6]<<8)+header[7]
track_num = (header[8]<<8)+header[9]
resolution = (header[12]<<8)+header[13]
print """header:
format:{}
track_num:{}
resolution:{}""".format(format_, track_num, resolution)
i = 14
tracks = []
while i < len(data) :
track_len = (data[i+4]<<24)+(data[i+5]<<16)+(data[i+6]<<8)+data[i+7]
next_i = i+track_len+8
tracks.append(data[i+8:next_i])
i = next_i
for track in tracks :
i = 0
while i < len(track) :
#parse deltatime
deltatime = 0
while True :
data = track[i]
i += 1
deltatime <<= 7
deltatime += data&0x7f
if ((data>>7) & 1) == 0: break
print "deltatime:",
print deltatime
try :
duration_us = float(deltatime)/float(resolution)*float(tempo)
except NameError :
duration_us = 0.0
if (track[i]&0xf0) == 0xf0 :
# meta event
if (track[i]&0x0f) == 0x0f :
i += 1
event_type = track[i]
i += 1
event_len = track[i]
i += 1
event_data = track[i:i+event_len]
i += event_len
if event_type == 0x08 :
print "program name:",
print ''.join(map(chr, event_data))
elif event_type == 0x03 :
print "seqence name:",
print ''.join(map(chr, event_data))
elif event_type == 0x02 :
print "copyright:",
print ''.join(map(chr, event_data))
elif event_type == 0x01 :
print "text:",
print ''.join(map(chr, event_data))
elif event_type == 0x2f :
i += 1
print "track end:"
elif event_type == 0x51 :
tempo = (event_data[0]<<16) + (event_data[1]<<8) + event_data[2]
print "tempo:{}".format(tempo)
elif event_type == 0x58 :
nn = event_data[0]
dd = event_data[1]
bb = event_data[2]
cc = event_data[3]
print "hyoshi:{}/{}".format(nn, 2**dd)
elif event_type == 0x59 :
sf = event_data[0]
mi = event_data[1]
print "tyogo:", sf, mi
elif event_type == 0x7f:
origin_event = event_data[1:]
print "origin event:", origin_event
else :
print "unknown meta event:",
print hex(event_type),
print event_data
# SysEx event
else :
sysex_type = track[i]
i += 1
event_len = track[i]
i += 1
event_data = track[i:i+event_len]
i += event_len
if sysex_type == 0xF0 :
print "F0 SysEx :",
print event_data
elif sysex_type == 0xF7 :
print "F7 SysEx :",
print event_data
else :
print "unknown SysEx event:",
print map(hex, track[i:i+8])
# midi event
else :
if (track[i]&0x80) == 0x80 :
status_byte = track[i]
i += 1
else :
pass
n = status_byte&0x0f
if (status_byte&0xf0) == 0x80 :
kk = track[i]
i += 1
vv = track[i]
i += 1
print """note off:
n:{}
kk:{}
vv:{}""".format(n,kk,vv)
freq = 440.0 * pow(2.0, (kk - 69.0) / 12.0)
callback(0, duration_us)
elif (status_byte&0xf0) == 0x90 :
kk = track[i]
i += 1
vv = track[i]
i += 1
print """note on:
n:{}
kk:{}
vv:{}""".format(n,kk,vv)
freq = 440.0 * pow(2.0, (kk - 69.0) / 12.0)
callback(freq, duration_us)
elif (status_byte&0xf0) == 0xa0 :
kk = track[i]
i += 1
vv = track[i]
i += 1
print """polifonic keep pressure:
n:{}
kk:{}
vv:{}""".format(n,kk,vv)
freq = 440.0 * pow(2.0, (kk - 69.0) / 12.0)
callback(0, tempo*(1/32.0))
callback(freq, duration_us-tempo*(1/32.0))
elif (status_byte&0xf0) == 0xb0 :
cc = track[i]
i += 1
vv = track[i]
i += 1
print """control change:
n:{}
cc:{}
vv:{}""".format(n,cc,vv)
try :
freq = 440.0 * pow(2.0, (kk - 69.0) / 12.0)
callback(freq, duration_us)
except NameError :
pass
elif (status_byte&0xf0) == 0xc0 :
pp = track[i]
i += 1
print """program change:
n:{}
pp:{}""".format(n,pp)
elif (status_byte&0xf0) == 0xe0 :
mm = track[i]
i += 1
ll = track[i]
i += 1
print """pitch bend:
n:{}
mm:{}
ll:{}""".format(n,mm,ll)
else :
print "unknown midi event:",
print hex(status_byte), map(hex, track[i:i+8])
if __name__ == '__main__':
def callback(freq, duration_us) :
if 0 < freq:
p = subprocess.Popen(["beep", "-l", str(duration_us/1000.0), "-f", str(freq)])
p.wait()
else :
time.sleep(duration_us/1000.0/1000.0)
midi_play("./20111219165842b4a.mid", callback)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment