- s = ''
- bar_t = time.bar_clocks ()
- if t - last_bar_t >= bar_t:
- bar_count = bar_count + (t - last_bar_t) / bar_t
-
- if t - last_bar_t == bar_t:
- s = '|\n %% %d\n ' % bar_count
- last_bar_t = t
- else:
- # urg, this will barf at meter changes
- last_bar_t = last_bar_t + (t - last_bar_t) / bar_t * bar_t
-
- return (s, last_bar_t, bar_count)
-
-
-def dump_channel (thread, skip):
- global key, reference_note, time
-
- key = Key (0, 0, 0)
- time = Time (4, 4)
- # urg LilyPond doesn't start at c4, but
- # remembers from previous tracks!
- # reference_note = Note (clocks_per_4, 4*12, 0)
- reference_note = Note (0, 4*12, 0)
- last_e = None
- chs = []
- ch = []
-
- for e in thread:
- if last_e and last_e[0] == e[0]:
- ch.append (e[1])
- else:
- if ch:
- chs.append ((last_e[0], ch))
-
- ch = [e[1]]
-
- last_e = e
-
- if ch:
- chs.append ((last_e[0], ch))
- t = 0
- last_t = 0
- last_bar_t = 0
- bar_count = 1
-
- lines = ['']
- for ch in chs:
- t = ch[0]
-
- i = string.rfind (lines[-1], '\n') + 1
- if len (lines[-1][i:]) > LINE_BELL:
- lines.append ('')
-
- if t - last_t > 0:
- lines[-1] = lines[-1] + dump_skip (skip, t-last_t)
- elif t - last_t < 0:
- errorport.write ('BUG: time skew')
-
- (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
- t, bar_count)
- lines[-1] = lines[-1] + s
-
- lines[-1] = lines[-1] + dump_chord (ch[1])
-
- clocks = 0
- for i in ch[1]:
- if i.clocks > clocks:
- clocks = i.clocks
-
- last_t = t + clocks
-
- (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
- last_t, bar_count)
- lines[-1] = lines[-1] + s
-
- return string.join (lines, '\n ') + '\n'
-
-def track_name (i):
- return 'track%c' % (i + ord ('A'))
-
-def channel_name (i):
- return 'channel%c' % (i + ord ('A'))
-
-def dump_track (channels, n):
- s = '\n'
- track = track_name (n)
- clef = guess_clef (channels)
-
- for i in range (len (channels)):
- channel = channel_name (i)
- item = thread_first_item (channels[i])
-
- if item and item.__class__ == Note:
- skip = 's'
- s = s + '%s = ' % (track + channel)
- if not global_options.absolute_pitches:
- s = s + '\\relative c '
- elif item and item.__class__ == Text:
- skip = '" "'
- s = s + '%s = \\lyricmode ' % (track + channel)
- else:
- skip = '\\skip '
- s = s + '%s = ' % (track + channel)
- s = s + '{\n'
- s = s + ' ' + dump_channel (channels[i][0], skip)
- s = s + '}\n\n'
-
- s = s + '%s = <<\n' % track
-
- if clef.type != 2:
- s = s + clef.dump () + '\n'
-
- for i in range (len (channels)):
- channel = channel_name (i)
- item = thread_first_item (channels[i])
- if item and item.__class__ == Text:
- s = s + ' \\context Lyrics = %s \\%s\n' % (channel,
- track + channel)
- else:
- s = s + ' \\context Voice = %s \\%s\n' % (channel,
- track + channel)
- s = s + '>>\n\n'
- return s
-
-def thread_first_item (thread):
- for chord in thread:
- for event in chord:
- if (event[1].__class__ == Note
- or (event[1].__class__ == Text
- and event[1].type == midi.LYRIC)):
-
- return event[1]
- return None
+ s = ''
+ bar_t = time.bar_clocks ()
+ if t - last_bar_t >= bar_t:
+ bar_count = bar_count + (t - last_bar_t) / bar_t
+
+ if t - last_bar_t == bar_t:
+ s = '\n | %% %(bar_count)d\n ' % locals ()
+ last_bar_t = t
+ else:
+ # urg, this will barf at meter changes
+ last_bar_t = last_bar_t + (t - last_bar_t) / bar_t * bar_t
+
+ return (s, last_bar_t, bar_count)
+
+
+def dump_voice (thread, skip):
+ global reference_note, time
+ ref = Note (0, 4*12, 0)
+ if not reference_note:
+ reference_note = ref
+ else:
+ ref.duration = reference_note.duration
+ reference_note = ref
+ last_e = None
+ chs = []
+ ch = []
+
+ for e in thread:
+ if last_e and last_e[0] == e[0]:
+ ch.append (e[1])
+ else:
+ if ch:
+ chs.append ((last_e[0], ch))
+
+ ch = [e[1]]
+
+ last_e = e
+
+ if ch:
+ chs.append ((last_e[0], ch))
+ t = 0
+ last_t = 0
+ last_bar_t = 0
+ bar_count = 1
+
+ lines = ['']
+ for ch in chs:
+ t = ch[0]
+
+ i = lines[-1].rfind ('\n') + 1
+ if len (lines[-1][i:]) > LINE_BELL:
+ lines.append ('')
+
+ if t - last_t > 0:
+ d = t - last_t
+ if bar_max and t > time.bar_clocks () * bar_max:
+ d = time.bar_clocks () * bar_max - last_t
+ lines[-1] = lines[-1] + dump_skip (skip, d)
+ elif t - last_t < 0:
+ errorport.write ('BUG: time skew')
+
+ (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
+ t, bar_count)
+
+ if bar_max and bar_count > bar_max:
+ break
+
+ lines[-1] = lines[-1] + s
+ lines[-1] = lines[-1] + dump_chord (ch[1])
+
+ clocks = 0
+ for i in ch[1]:
+ if i.clocks > clocks:
+ clocks = i.clocks
+
+ last_t = t + clocks
+
+ (s, last_bar_t, bar_count) = dump_bar_line (last_bar_t,
+ last_t, bar_count)
+ lines[-1] = lines[-1] + s
+
+ return '\n '.join (lines) + '\n'
+
+def number2ascii (i):
+ s = ''
+ i += 1
+ while i > 0:
+ m = (i - 1) % 26
+ s = '%c' % (m + ord ('A')) + s
+ i = (i - m)/26
+ return s
+
+def get_track_name (i):
+ return 'track' + number2ascii (i)
+
+def get_channel_name (i):
+ return 'channel' + number2ascii (i)
+
+def get_voice_name (i, zero_too_p=False):
+ if i or zero_too_p:
+ return 'voice' + number2ascii (i)
+ return ''
+
+def lst_append (lst, x):
+ lst.append (x)
+ return lst
+
+def get_voice_layout (average_pitch):
+ d = {}
+ for i in range (len (average_pitch)):
+ d[average_pitch[i]] = lst_append (d.get (average_pitch[i], []), i)
+ s = list (reversed (sorted (average_pitch)))
+ non_empty = len (filter (lambda x: x, s))
+ names = ['One', 'Two']
+ if non_empty > 2:
+ names = ['One', 'Three', 'Four', 'Two']
+ layout = map (lambda x: '', range (len (average_pitch)))
+ for i, n in zip (s, names):
+ if i:
+ v = d[i]
+ if type (v) == list:
+ d[i] = v[1:]
+ v = v[0]
+ layout[v] = n
+ return layout
+
+def dump_track (track, n):
+ s = '\n'
+ track_name = get_track_name (n)
+
+ average_pitch = track_average_pitch (track)
+ voices = len (filter (lambda x: x, average_pitch[1:]))
+ clef = get_best_clef (average_pitch[0])
+
+ c = 0
+ vv = 0
+ for channel in track:
+ v = 0
+ channel_name = get_channel_name (c)
+ c += 1
+ for voice in channel:
+ voice_name = get_voice_name (v)
+ voice_id = track_name + channel_name + voice_name
+ item = voice_first_item (voice)
+
+ if item and item.__class__ == Note:
+ skip = 'r'
+ if global_options.skip:
+ skip = 's'
+ s += '%(voice_id)s = ' % locals ()
+ if not global_options.absolute_pitches:
+ s += '\\relative c '
+ elif item and item.__class__ == Text:
+ skip = '" "'
+ s += '%(voice_id)s = \\lyricmode ' % locals ()
+ else:
+ skip = '\\skip '
+ s += '%(voice_id)s = ' % locals ()
+ s += '{\n'
+ if not n and not vv and global_options.key:
+ s += global_options.key.dump ()
+ if average_pitch[vv+1] and voices > 1:
+ vl = get_voice_layout (average_pitch[1:])[vv]
+ if vl:
+ s += ' \\voice' + vl + '\n'
+ else:
+ if not global_options.quiet:
+ warning (_ ('found more than 5 voices on a staff, expect bad output'))
+ s += ' ' + dump_voice (voice, skip)
+ s += '}\n\n'
+ v += 1
+ vv += 1
+
+ s += '%(track_name)s = <<\n' % locals ()
+
+ if clef.type != 2:
+ s += clef.dump () + '\n'
+
+ c = 0
+ vv = 0
+ for channel in track:
+ v = 0
+ channel_name = get_channel_name (c)
+ c += 1
+ for voice in channel:
+ voice_context_name = get_voice_name (vv, zero_too_p=True)
+ voice_name = get_voice_name (v)
+ v += 1
+ vv += 1
+ voice_id = track_name + channel_name + voice_name
+ item = voice_first_item (voice)
+ context = 'Voice'
+ if item and item.__class__ == Text:
+ context = 'Lyrics'
+ s += ' \\context %(context)s = %(voice_context_name)s \\%(voice_id)s\n' % locals ()
+ s += '>>\n\n'
+ return s
+
+def voice_first_item (voice):
+ for event in voice:
+ if (event[1].__class__ == Note
+ or (event[1].__class__ == Text
+ and event[1].type == midi.LYRIC)):
+ return event[1]
+ return None
+
+def channel_first_item (channel):
+ for voice in channel:
+ first = voice_first_item (voice)
+ if first:
+ return first
+ return None