-
Notifications
You must be signed in to change notification settings - Fork 4
/
midi2note.lua
executable file
·100 lines (92 loc) · 1.96 KB
/
midi2note.lua
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env lua
local parse=require("argparse")
local args, opts=parse(...)
local function print(...)
local args=table.pack(...)
for i=1, args.n do
args[i]=tostring(args[i])
end
io.stderr:write(table.concat(args, "\t").."\n")
end
if #args < 1 then
print("Usage: " .. (arg and arg[0] or "midi2note") .. " midifile [notefile]")
return 0
end
local file, err=io.open(args[1], "rb")
if not file then
print(err)
os.exit(1)
end
local data=file:read("*a")
file:close()
local text_events={
text_event=true,
copyright_text_event=true,
track_name=true,
instrument_name=true,
lyric=true,
marker=true,
cue_point=true,
text_event_08=true,
text_event_09=true,
text_event_0a=true,
text_event_0b=true,
text_event_0c=true,
text_event_0d=true,
text_event_0e=true,
text_event_0f=true,
}
local function score2note(score)
local note={score[1]}
local trackpos={}
local nscore=#score
for i=2, nscore do
trackpos[i]=1
end
while true do
local ltime, tpos=math.huge
for i=2, nscore do
local event=score[i][trackpos[i]]
if event then
local ttime=event[2]
if ttime < ltime then
ltime, tpos=ttime, i
end
end
end
if not tpos then break end
local event=score[tpos][trackpos[tpos]]
score[tpos][trackpos[tpos]]=nil
trackpos[tpos]=trackpos[tpos] + 1
table.insert(event, 3, tpos-2)
-- Merge text events into one event type
local kind=event[1]
if text_events[kind] then
kind=kind:gsub("_event", ""):gsub("_text", "")
table.insert(event, 4, kind)
event[1]="text"
end
note[#note+1]=event
end
return note
end
local midi=require("MIDI")
local note=score2note(midi.midi2score(data))
local outfile, err
if args[2] then
print("Writing to '" .. args[2] .. "'")
outfile, err=io.open(args[2], "wb")
if not outfile then
error(err, 0)
end
else
print("Writing to stdout")
outfile=io.stdout
end
outfile:write("Ticks per beat: " .. note[1].."\n")
for i=2, #note do
outfile:write(table.concat(note[i], ", ").."\n")
end
if args[2] then
outfile:close()
end