8 scale_steps = [0,2,4,5,7,9,11]
10 def split_track (track):
17 if data[0] > 0x7f and data[0] < 0xf0:
19 e = (e[0], tuple ([data[0] & 0xf0] + data[1:]))
29 for v in chs.values ():
30 ns = notes_on_channel (v)
31 dinges = unthread_notes (ns)
33 whatarewes.append (dinges)
38 def __init__ (self, duration, pitch, velocity):
39 self.velocity = velocity
41 self.duration = duration
43 def duration_compare (a, b):
44 if a.duration < b.duration:
46 elif a.duration > b.duration:
52 return dump_note (self)
55 def __init__ (self, t, num, den):
61 return dump_skip (self.duration) + '\\time %d/%d ' % (self.num, self.den)
64 key_sharps = ('c', 'g', 'd', 'a', 'e', 'b', 'fis')
65 key_flats = ('BUG', 'f', 'bes', 'es', 'as', 'des', 'ges')
67 def __init__ (self, t, sharps, flats, minor):
74 if self.sharps and self.flats:
75 s = '\\keysignature %s ' % 'TODO'
77 s = '\\notes\\key %s \major' % key_sharps[self.sharps]
79 s = '\\notes\\key %s \major' % key_flats[self.flats]
80 return dump_skip (self.duration) + s
84 def __init__ (self, text):
89 return dump_text (self)
91 def notes_on_channel (channel):
98 if e[1][0] == midi.NOTE_ON:
99 if not pitches.has_key (e[1][1]):
100 pitches[e[1][1]] = (t, e[1][2])
101 elif e[1][0] == midi.NOTE_OFF:
103 (lt, vel) = pitches[e[1][1]]
106 nch.append ((t, Note (t-lt, e[1][1], vel)))
110 elif e[1][0] == midi.META_EVENT:
111 if e[1][1] == midi.TIME_SIGNATURE:
112 (num, den, clocks4, count32) = map (ord, e[1][2])
113 nch.append ((t, Time (t, num, den)))
114 elif e[1][1] == midi.KEY_SIGNATURE:
115 (accidentals, minor) = map (ord, e[1][2])
118 if accidentals < 127:
121 flats = 256 - accidentals
122 nch.append ((t, Key (t, sharps, flats, minor)))
123 elif e[1][1] == midi.TEXT_EVENT:
124 nch.append ((t, Text (e[1][2])))
126 sys.stderr.write ("SKIP: %s\n" % `e`)
129 sys.stderr.write ("SKIP: %s\n" % `e`)
134 def unthread_notes (channel):
143 if e[1].__class__ == Note and ((t == start_busy_t and e[1].duration + t == end_busy_t) \
147 end_busy_t = t + e[1].duration
148 elif e[1].__class__ == Time or e[1].__class__ == Key or e[1].__class__ == Text:
152 threads.append (thread)
168 return 's' + dump_duration (dt)
170 def dump_duration (dur):
173 (p,q) = (dur / g, 384 / g)
174 if (p == 1 and q == 1) :
183 def dump_note (note):
189 while i < len (scale_steps):
190 if scale_steps[i] > step:
195 str = chr ((i + 2) % 7 + ord ('a'))
196 if scale_steps[i] <> step:
199 return ' %s' % str + dump_duration (note.duration)
204 def dump_text (text):
205 return '\n % ' + text.text + '\n '
212 s = '<' + string.join (map (dump, ch)) + '>'
216 def dump_channel (thread):
222 if last_e and last_e[0] == e[0]:
226 chs.append ((last_e[0], ch))
233 chs.append ((last_e[0], ch))
239 if len (lines[-1]) > LINE_BELL:
244 lines[-1] = lines[-1] + dump_skip (t-last_t)
246 lines[-1] = lines[-1] + dump_chord (ch[1])
248 last_t = t + ch[1][0].duration
250 return string.join (lines, '\n ') + '\n'
252 def dump_notes (channel):
257 s = s + dump_chord (on_hold)
265 return 'track%c' % (i + ord ('A'))
267 def channel_name (i):
268 return 'channel%c' % (i + ord ('A'))
270 def dump_track (channels, n):
272 track = track_name (n)
273 for i in range (len (channels)):
274 channel = channel_name (i)
275 s = s + '%s = \\notes {\n' % (track + channel)
276 s = s + ' ' + dump_channel (channels[i][0])
279 s = s + '%s = <\n' % track
281 for i in range (len (channels)):
282 channel = channel_name (i)
283 s = s + ' \\context Voice = %s \\%s\n' % (channel, track + channel)
288 def convert_midi (f):
289 str = open (f).read ()
290 midi_dump = midi.parse (str)
293 for t in midi_dump[1]:
294 tracks.append (split_track (t))
297 for i in range (len (tracks)):
298 s = s + dump_track (tracks[i], i)
300 s = s + '\n\\score {\n <\n'
301 for i in range (len (tracks)):
302 track = track_name (i)
303 s = s + ' \\context Staff=%s \\%s\n' % (track, track)
309 for f in sys.argv[1:]: