def time_signature(self, t, _=None): numerator = t.numerator() denominator = t.fraction().denominator if self.unit_length == None: self.bar_manager = BarManager(numerator, denominator, self.outputter, self.note_context) self.unit_length = self.default_unit_length(numerator, denominator) self.outputter.output_info_field("M: %s" % self.bar_manager.time_signature()) self.outputter.output_info_field("L: %s" % self.unit_length) self.note_context.unit_length = self.unit_length else: # meter change self.bar_manager.set_time_signature(numerator, denominator)
def __init__(self, music, outputter=OutputBuffer(FilehandleOutputter(sys.stdout)), output_assigns=None): self.outputter = outputter self.note_context = NoteContext() self.unit_length = None self.relative_mode = False self.music = music self.section = None self.note_buffer = [] self.chords = [] self.old_duration = 0 self.output_assigns = output_assigns self.bar_manager = BarManager(4, 4, self.outputter, self.note_context)
class LilypondMusic: def __init__(self, music, outputter=OutputBuffer(FilehandleOutputter(sys.stdout)), output_assigns=None): self.outputter = outputter self.note_context = NoteContext() self.unit_length = None self.relative_mode = False self.music = music self.section = None self.note_buffer = [] self.chords = [] self.old_duration = 0 self.output_assigns = output_assigns self.bar_manager = BarManager(4, 4, self.outputter, self.note_context) def traverse(self, node, handlers, i=0): method = handlers.get(type(node)) if method: method(node, handlers) else: for child in node: self.traverse(child, handlers) def output_abc(self): handlers = { ly.music.items.TimeSignature: self.time_signature, ly.music.items.KeySignature: self.key_signature, ly.music.items.Relative: self.relative, ly.music.items.ChordMode: self.chord_mode, ly.music.items.Assignment: self.assign, ly.music.items.Transpose: self.transpose, ly.music.items.MusicList: self.music_list, } self.traverse(self.music, handlers) self.pass_time() self.interpolate_chords() def interpolate_chords(self): buffers = self.outputter.outputter.buffers chord_time = 0 note_time = 0 buffer_index = 0 while buffers[buffer_index].duration == 0: buffer_index += 1 for (chord, duration) in self.chords: if chord: buffers[buffer_index].output_chord(chord) chord_time += duration while (note_time < chord_time): next_time = buffers[buffer_index].duration if note_time + next_time <= chord_time: note_time += next_time buffer_index += 1 else: break def time_signature(self, t, _=None): numerator = t.numerator() denominator = t.fraction().denominator if self.unit_length == None: self.bar_manager = BarManager(numerator, denominator, self.outputter, self.note_context) self.unit_length = self.default_unit_length(numerator, denominator) self.outputter.output_info_field("M: %s" % self.bar_manager.time_signature()) self.outputter.output_info_field("L: %s" % self.unit_length) self.note_context.unit_length = self.unit_length else: # meter change self.bar_manager.set_time_signature(numerator, denominator) def key_signature(self, k, _=None): self.note_context.transposer.transpose(k.pitch()) key = Key(k.pitch(), k.mode()) self.note_context.sharps = key.sharps() self.outputter.output_info_field("K: %s" % (key.to_abc())) def transpose(self, node, handlers): old_transposer = self.note_context.transposer self.note_context.transposer = ly.pitch.transpose.Transposer( node[0].pitch, node[1].pitch) for child in node[2:]: self.traverse(child, handlers) self.note_context.transposer = old_transposer def chord_mode(self, node, _=None): handlers = { ly.music.items.Note: self.chord_note, ly.music.items.Skip: self.chord_skip, ly.music.items.ChordSpecifier: self.chord_specifier } self.traverse(node, handlers) def chord_note(self, n, _=None): pitch = n.pitch.copy() self.note_context.transposer.transpose(pitch) pitch_map = {'': '', 'is': '#', 'es': 'b', 's': '#', 'f': 'b'} # need to map pitch to abc chord name - use both nl and english names pitchname = pitch.output() pitchname = re.sub(r"[,']", '', pitchname) notename = pitchname[0].upper() modifier = pitch_map[pitchname[1:]] if pitchname == 'es': modifier = 'b' self.chords.append((notename + modifier, n.length())) def chord_specifier(self, n, _=None): handlers = {ly.music.items.ChordItem: self.chord_item} self.traverse(n, handlers) def chord_item(self, item, _=None): if (item.token != ':'): (chord, length) = self.chords[-1] self.chords[-1] = (chord + item.token, length) def chord_skip(self, s, _=None): self.chords.append([None, s.length()]) def assign(self, node, handlers): if self.output_assigns == None or node.name() in self.output_assigns: for child in node: self.traverse(child, handlers) def relative(self, r, _=None): def note(n, _=None): self.last_pitch = n.pitch handlers = { ly.music.items.Note: note, ly.music.items.MusicList: self.music_list, ly.music.items.Transpose: self.transpose, } self.relative_mode = True self.traverse(r, handlers) self.relative_mode = False def note(self, n, _=None): duration = n.length() pitch = n.pitch.copy() if self.relative_mode: pitch.makeAbsolute(self.last_pitch) self.last_pitch = pitch.copy() self.note_context.transposer.transpose(pitch) self.print_note(pitch, duration) def tie(self, n, _=None): self.outputter.output_tie() def partial(self, p, _=None): duration = p.partial_length() self.outputter = self.bar_manager.pass_time(-duration) def rest(self, r, _=None): duration = r.length() self.print_note(None, duration) def repeat(self, r, handlers=None): if (r.specifier() == 'volta'): self.outputter.markup_to_bar() if self.outputter.barline == ":|": self.bar_manager.manual_bar("::") else: self.bar_manager.manual_bar("|:") self.repeat_count = r.repeat_count() for n in r: self.traverse(n, handlers) self.outputter.markup_to_bar() self.bar_manager.manual_bar(":|") elif (r.specifier() == 'unfold'): for i in range(0, r.repeat_count()): for n in r: self.traverse(n, handlers) else: sys.stsderr.write( "WARNING: Ignoring unhandled repeat specifier %s\n" % r.specifier()) def alternative(self, a, handlers={}): def output_alternative(alt_range, music_list): self.outputter.output_volta(" [%s " % alt_range) self.traverse(music_list, handlers) self.bar_manager.manual_bar(":|]") for music_list in a: alt_range = "1" if self.repeat_count > len(music_list): alt_range = "1-%d" % (self.repeat_count - len(music_list) + 1) output_alternative(alt_range, music_list[0]) alternative = self.repeat_count - len(music_list) + 2 if len(music_list) >= 3: for ending in music_list[1:-1]: output_alternative(str(alternative), ending) alternative += 1 if len(music_list) >= 2: # last ending - would be rather odd not to have this self.outputter.output_volta((" [%d ") % alternative) self.traverse(music_list[-1], handlers) self.repeat_count = None def markup(self, node, _=None): self.outputter.previous.output_markup("^" + node.plaintext()) def music_list(self, m, _=None): handlers = { ly.music.items.Note: self.note, ly.music.items.Tie: self.tie, ly.music.items.Rest: self.rest, ly.music.items.TimeSignature: self.time_signature, ly.music.items.KeySignature: self.key_signature, ly.music.items.Repeat: self.repeat, ly.music.items.Alternative: self.alternative, ly.music.items.Command: self.command, ly.music.items.UserCommand: self.usercommand, ly.music.items.Partial: self.partial, ly.music.items.Transpose: self.transpose, ly.music.items.Markup: self.markup, ly.music.items.Relative: self.relative, ly.music.items.ChordMode: self.chord_mode, } self.traverse(m, handlers) def next_mark(self): if not self.section: self.section = 'A' else: self.section = chr(ord(self.section) + 1) return self.section def usercommand(self, usercommand, handlers): if (usercommand.name() == 'ppMark'): self.outputter.output_markup("^%s" % self.next_mark()) else: r = re.match(r'ppMark(\w)', usercommand.name()) if r: self.outputter.previous.output_markup("^%s" % r.group(1)) for n in usercommand: self.traverse(usercommand, handlers) def command(self, m, _=None): def bar(): bars = { "|": "|", "||": "||", ".|": "[|", "|.": "|]", ".|:": "|:", ":..:": "::", ":|.|:": "::", ":|.:": "::", ":.|.:": "::", "[|:": "|:", ":|][|:": "::", ":|]": ":|", ":|.": ":|", ":|": ":|", "|:": "|:", ":|:": "::", } self.bar_manager.manual_bar((bars.get(m.next_sibling().plaintext(), '|'))) def mark(): if (isinstance(m.next_sibling(), ly.music.items.String)): thismark = m.next_sibling().plaintext() else: thismark = self.next_mark() self.outputter.output_markup("^%s" % thismark) if (m.token == "\\bar"): bar() if (m.token == "\\mark"): mark() # private def print_note(self, pitch, duration): self.pass_time() self.outputter.output_note( Note(pitch, duration, self.note_context).to_abc(), duration) self.old_duration += duration def default_unit_length(self, numerator, denominator): if Fraction(numerator, denominator) < Fraction(3, 4): return Fraction(1, 16) elif denominator <= 2: return Fraction(1, 4) else: return Fraction(1, 8) def pass_time(self): self.outputter = self.bar_manager.pass_time(self.old_duration) self.old_duration = 0
def bar_manager(self): return BarManager(3, 4)
def bar_manager(self): return BarManager(6, 8, outputter=OutputBuffer(TestOutputter()))
bar_manager.pass_time(Fraction(3, 4)) expect(bar_manager.beam_break()).to(equal(True)) with it('puts a line break after 12 measures have passed'): bar_manager = self.bar_manager() bar_manager.pass_time(Fraction(12 * 3, 4)) expect(bar_manager.line_break()).to(equal(True)) with it('does not put a line break after 5 measures have passed'): bar_manager = self.bar_manager() bar_manager.pass_time(Fraction(5 * 3, 4)) expect(bar_manager.line_break()).to(equal(False)) with it('puts a bar line after five measures have passed'): bar_manager = self.bar_manager() bar_manager.pass_time(Fraction(5 * 3, 4)) expect(bar_manager.bar_line()).to(equal(True)) with it('does not put a bar line after one measure and one beat have passed' ): bar_manager = self.bar_manager() bar_manager.pass_time(Fraction(5, 4)) expect(bar_manager.bar_line()).to(equal(False)) with description("time_signature"): with it('returns 6/8 for 6/8'): expect(BarManager(6, 8).time_signature()).to(equal("6/8")) with it('returns 4/4 for 4/4'): expect(BarManager(4, 4).time_signature()).to(equal("4/4"))