8 scale_steps = [0,2,4,5,7,9,11]
13 def split_track (track):
20 if data[0] > 0x7f and data[0] < 0xf0:
22 e = (e[0], tuple ([data[0] & 0xf0] + data[1:]))
32 for v in chs.values ():
33 ns = notes_on_channel (v)
34 dinges = unthread_notes (ns)
36 whatarewes.append (dinges)
41 def __init__ (self, clocks, pitch, velocity):
42 self.velocity = velocity
46 def clocks_compare (a, b):
47 if a.clocks < b.clocks:
49 elif a.clocks > b.clocks:
55 return dump_note (self)
58 def __init__ (self, t, num, den):
67 s = dump_skip (self.skip)
69 return s + '\\time %d/%d ' % (self.num, self.den) + '\n '
72 key_sharps = ('c', 'g', 'd', 'a', 'e', 'b', 'fis')
73 key_flats = ('BUG', 'f', 'bes', 'es', 'as', 'des', 'ges')
75 def __init__ (self, t, sharps, flats, minor):
85 s = dump_skip (self.skip)
87 if self.sharps and self.flats:
88 s = '\\keysignature %s ' % 'TODO'
90 s = '\\notes\\key %s \major' % self.key_sharps[self.sharps]
92 s = '\\notes\\key %s \major' % self.key_flats[self.flats]
97 def __init__ (self, t, text):
105 s = dump_skip (self.skip)
106 return s + dump_text (self)
108 def notes_on_channel (channel):
115 if e[1][0] == midi.NOTE_ON:
116 if not pitches.has_key (e[1][1]):
117 pitches[e[1][1]] = (t, e[1][2])
118 elif e[1][0] == midi.NOTE_OFF:
120 (lt, vel) = pitches[e[1][1]]
123 nch.append ((lt, Note (t-lt, e[1][1], vel)))
127 elif e[1][0] == midi.META_EVENT:
128 if e[1][1] == midi.TIME_SIGNATURE:
129 (num, den, clocks4, count32) = map (ord, e[1][2])
130 nch.append ((t, Time (t, num, den)))
131 elif e[1][1] == midi.KEY_SIGNATURE:
132 (accidentals, minor) = map (ord, e[1][2])
135 if accidentals < 127:
138 flats = 256 - accidentals
139 nch.append ((t, Key (t, sharps, flats, minor)))
140 elif e[1][1] == midi.TEXT_EVENT:
141 nch.append ((t, Text (t, e[1][2])))
143 sys.stderr.write ("SKIP: %s\n" % `e`)
146 sys.stderr.write ("SKIP: %s\n" % `e`)
151 def unthread_notes (channel):
160 if e[1].__class__ == Note and ((t == start_busy_t and e[1].clocks + t == end_busy_t) \
164 end_busy_t = t + e[1].clocks
165 elif e[1].__class__ == Time or e[1].__class__ == Key or e[1].__class__ == Text:
169 threads.append (thread)
184 def dump_skip (clocks):
185 return 's' + dump_duration (clocks) + ' '
187 def dump_duration (clocks):
188 g = gcd (clocks, whole_clocks)
189 (d, n) = (whole_clocks/ g, clocks / g)
192 elif n == 3 and d != 1:
198 def dump_note (note):
204 while i < len (scale_steps):
205 if scale_steps[i] > step:
210 str = chr ((i + 2) % 7 + ord ('a'))
211 if scale_steps[i] <> step:
214 return str + dump_duration (note.clocks) + ' '
219 def dump_text (text):
220 return '\n % ' + text.text + '\n '
227 s = '<' + string.join (map (dump, ch)) + '>'
231 def dump_channel (thread):
237 if last_e and last_e[0] == e[0]:
241 chs.append ((last_e[0], ch))
248 chs.append ((last_e[0], ch))
254 if len (lines[-1]) > LINE_BELL:
259 lines[-1] = lines[-1] + dump_skip (t-last_t)
261 lines[-1] = lines[-1] + dump_chord (ch[1])
263 last_t = t + ch[1][0].clocks
265 return string.join (lines, '\n ') + '\n'
267 def dump_notes (channel):
272 s = s + dump_chord (on_hold)
280 return 'track%c' % (i + ord ('A'))
282 def channel_name (i):
283 return 'channel%c' % (i + ord ('A'))
285 def dump_track (channels, n):
287 track = track_name (n)
288 for i in range (len (channels)):
289 channel = channel_name (i)
290 s = s + '%s = \\notes {\n' % (track + channel)
291 s = s + ' ' + dump_channel (channels[i][0])
294 s = s + '%s = <\n' % track
296 for i in range (len (channels)):
297 channel = channel_name (i)
298 s = s + ' \\context Voice = %s \\%s\n' % (channel, track + channel)
303 def convert_midi (f):
304 global whole_clocks, quart_clocks
306 str = open (f).read ()
307 midi_dump = midi.parse (str)
309 whole_clocks = midi_dump[0][1]
310 quart_clocks = whole_clocks / 4
313 for t in midi_dump[1]:
314 tracks.append (split_track (t))
317 for i in range (len (tracks)):
318 s = s + dump_track (tracks[i], i)
320 s = s + '\n\\score {\n <\n'
321 for i in range (len (tracks)):
322 track = track_name (i)
323 s = s + ' \\context Staff=%s \\%s\n' % (track, track)
329 for f in sys.argv[1:]: