def _beam_rhythm_containers(self, rhythm_containers): beam_cells_together = getattr( self.source_expression, 'beam_cells_together', False) beam_each_cell = getattr( self.source_expression, 'beam_each_cell', False) if beam_cells_together: for container in iterationtools.iterate_components_in_expr( rhythm_containers): spanners = container._get_spanners() for spanner in spanners: spanner.detach() durations = [x._get_duration() for x in rhythm_containers] beam = spannertools.DuratedComplexBeamSpanner( durations=durations, span=1, ) attach(beam, rhythm_containers) elif beam_each_cell: for container in iterationtools.iterate_components_in_expr( rhythm_containers): spanners = container._get_spanners() for spanner in spanners: spanner.detach() for rhythm_container in rhythm_containers: beam = spannertools.DuratedComplexBeamSpanner( durations=[rhythm_container._get_duration()], span=1, ) attach(beam, rhythm_container)
def _notate(self, grace_handler, attack_point_optimizer, attach_tempo_marks): voice = scoretools.Voice() # generate the first beat = self.items[0] components = beat.q_grid(beat.beatspan) if attach_tempo_marks: attachment_target = components[0] if isinstance(attachment_target, containertools.Container): attachment_target = attachment_target.select_leaves()[0] tempo = copy.copy(beat.tempo) attach(tempo, attachment_target) voice.extend(components) # generate the rest pairwise, comparing tempi for beat_one, beat_two in \ sequencetools.iterate_sequence_pairwise_strict(self.items): components = beat_two.q_grid(beat_two.beatspan) if (beat_two.tempo != beat_one.tempo) and attach_tempo_marks: attachment_target = components[0] if isinstance(attachment_target, containertools.Container): attachment_target = attachment_target.select_leaves()[0] tempo = copy.copy(beat_two.tempo) attach(tempo, attachment_target) voice.extend(components) # apply tie chains, pitches, grace containers self._notate_leaves_pairwise(voice, grace_handler) # partition tie chains in voice attack_point_optimizer(voice) return voice
def _construct_context_specced_music(self, context, optional_id, optional_context_mod, music): known_contexts = { "ChoirStaff": scoretools.StaffGroup, "GrandStaff": scoretools.GrandStaff, "PianoStaff": scoretools.PianoStaff, "Score": scoretools.Score, "Staff": stafftools.Staff, "StaffGroup": scoretools.StaffGroup, "Voice": scoretools.Voice, } if context in known_contexts: context = known_contexts[context]([]) else: raise Exception("Context type %s not supported." % context) if optional_id is not None: context.name = optional_id if optional_context_mod is not None: for x in optional_context_mod: print x pass # TODO: Implement context mods on contexts. # context.is_simultaneous = music.is_simultaneous # add children while len(music): component = music.pop(0) context.append(component) marks = music._start_marks for mark in marks: attach(mark, context) return context
def label_leaves_in_expr_with_tuplet_depth(expr, markup_direction=Down): r'''Label leaves in `expr` with tuplet depth: :: >>> staff = Staff("c'8 d'8 e'8 f'8 g'8") >>> tuplettools.FixedDurationTuplet(Duration(2, 8), staff[-3:]) FixedDurationTuplet(1/4, [e'8, f'8, g'8]) >>> labeltools.label_leaves_in_expr_with_tuplet_depth(staff) >>> f(staff) \new Staff { c'8 _ \markup { \small 0 } d'8 _ \markup { \small 0 } \times 2/3 { e'8 _ \markup { \small 1 } f'8 _ \markup { \small 1 } g'8 _ \markup { \small 1 } } } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for leaf in iterationtools.iterate_leaves_in_expr(expr): label = markuptools.MarkupCommand( 'small', str(leaf._get_parentage().tuplet_depth)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def _attach_tie_spanner_to_leaf_pair(self): from abjad.tools import leaftools from abjad.tools import spannertools from abjad.tools.scoretools import attach assert len(self) == 2 left_leaf, right_leaf = self assert isinstance(left_leaf, leaftools.Leaf), left_leaf assert isinstance(right_leaf, leaftools.Leaf), right_leaf left_tie_chain = left_leaf._get_tie_chain() right_tie_chain = right_leaf._get_tie_chain() spanner_classes = (spannertools.TieSpanner,) if left_tie_chain == right_tie_chain: return try: left_tie_spanner = left_leaf._get_spanner(spanner_classes) except MissingSpannerError: left_tie_spanner = None try: right_tie_spanner = right_leaf._get_spanner(spanner_classes) except MissingSpannerError: right_tie_spanner = None if left_tie_spanner is not None and right_tie_spanner is not None: left_tie_spanner.fuse(right_tie_spanner) elif left_tie_spanner is not None and right_tie_spanner is None: left_tie_spanner.append(right_leaf) elif left_tie_spanner is None and right_tie_spanner is not None: right_tie_spanner.append_left(left_leaf) elif left_tie_spanner is None and right_tie_spanner is None: tie = spannertools.TieSpanner() attach(tie, [left_leaf, right_leaf])
def __call__(self, expr): assert self.dynamics_talea, repr(self.dynamics_talea) groups = [] classes = (notetools.Note, scoretools.Chord) for i, group in enumerate( iterationtools.iterate_runs_in_expr( expr, classes)): spanner = spannertools.TextSpanner() attach(spanner, group) spanner.override.text_spanner.dash_fraction = 1 dynamic_string = self.dynamics_talea[i] dynamic_markup = markuptools.Markup([ markuptools.MarkupCommand('dynamic', dynamic_string), markuptools.MarkupCommand('hspace', 0.75)]) spanner.override.text_spanner.bound_details__left__text = \ dynamic_markup nib_markup = markuptools.Markup( markuptools.MarkupCommand( 'draw-line', schemetools.SchemePair(0, 1))) spanner.override.text_spanner.bound_details__right__text = \ nib_markup spanner.override.text_spanner.bound_details__right__padding = \ -0.2 spanner.override.text_spanner.bound_details__left__stencil_align_dir_y = 0 return groups
def label_leaves_in_expr_with_leaf_numbers(expr, markup_direction=Down): r'''Label leaves in `expr` with leaf numbers: :: >>> staff = Staff("c'8 d'8 e'8 f'8") >>> labeltools.label_leaves_in_expr_with_leaf_numbers(staff) >>> f(staff) \new Staff { c'8 _ \markup { \small 1 } d'8 _ \markup { \small 2 } e'8 _ \markup { \small 3 } f'8 _ \markup { \small 4 } } :: >>> show(staff) # doctest: +SKIP Number leaves starting from ``1``. Returns none. ''' for i, leaf in enumerate(iterationtools.iterate_leaves_in_expr(expr)): leaf_number = i + 1 label = markuptools.MarkupCommand('small', str(leaf_number)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def _scale(self, multiplier=None): from abjad.tools import containertools from abjad.tools import contexttools from abjad.tools import iterationtools from abjad.tools import timesignaturetools from abjad.tools.scoretools import attach if multiplier is None: return multiplier = durationtools.Multiplier(multiplier) old_time_signature = self.time_signature if mathtools.is_nonnegative_integer_power_of_two(multiplier) and \ 1 <= multiplier: old_numerator = old_time_signature.numerator old_denominator = old_time_signature.denominator new_denominator = old_denominator / multiplier.numerator pair = (old_numerator, new_denominator) new_time_signature = contexttools.TimeSignatureMark(pair) else: old_denominator = old_time_signature.denominator old_duration = old_time_signature.duration new_duration = multiplier * old_duration new_time_signature = \ timesignaturetools.duration_and_possible_denominators_to_time_signature( new_duration, [old_denominator], multiplier.denominator) for mark in self._get_marks(contexttools.TimeSignatureMark): mark.detach() attach(new_time_signature, self) contents_multiplier_denominator = \ mathtools.greatest_power_of_two_less_equal(multiplier.denominator) pair = (multiplier.numerator, contents_multiplier_denominator) contents_multiplier = durationtools.Multiplier(*pair) self._scale_contents(contents_multiplier)
def execute_against_score(self, score): r'''Execute markup set expression against `score`. ''' markup = self.source_expression.payload for leaf in self._iterate_selected_leaves_in_score(score): new_markup = markuptools.Markup(markup) attach(new_markup, leaf)
def label_leaves_in_expr_with_pitch_numbers(expr, markup_direction=Down): r'''Label leaves in `expr` with pitch numbers: :: >>> staff = Staff(leaftools.make_leaves([None, 12, [13, 14, 15], None], [(1, 4)])) >>> labeltools.label_leaves_in_expr_with_pitch_numbers(staff) >>> f(staff) \new Staff { r4 c''4 _ \markup { \small 12 } <cs'' d'' ef''>4 _ \markup { \column { \small 15 \small 14 \small 13 } } r4 } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for leaf in iterationtools.iterate_leaves_in_expr(expr): for pitch in reversed(pitchtools.PitchSegment.from_selection(leaf)): if pitch is not None: label = markuptools.MarkupCommand('small', str(pitch.pitch_number)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def label_leaves_in_expr_with_leaf_indices(expr, markup_direction=Down): r'''Label leaves in `expr` with leaf indices: :: >>> staff = Staff("c'8 d'8 e'8 f'8") >>> labeltools.label_leaves_in_expr_with_leaf_indices(staff) >>> f(staff) \new Staff { c'8 _ \markup { \small 0 } d'8 _ \markup { \small 1 } e'8 _ \markup { \small 2 } f'8 _ \markup { \small 3 } } :: >>> show(staff) # doctest: +SKIP Returns none. ''' for i, leaf in enumerate(iterationtools.iterate_leaves_in_expr(expr)): label = markuptools.MarkupCommand('small', str(i)) markup = markuptools.Markup(label, markup_direction) attach(markup, leaf)
def __call__(self, expr, offset=0): leaves = list(iterationtools.iterate_leaves_in_expr(expr)) groups = list(iterationtools.iterate_runs_in_expr( leaves, (notetools.Note, scoretools.Chord))) hairpin_tokens = datastructuretools.CyclicList(self.hairpin_tokens) for i, group in enumerate(groups): if not isinstance(group, selectiontools.SliceSelection): group = selectiontools.SliceSelection(group) is_short_group = False hairpin_token = hairpin_tokens[offset+i] if len(group) == 1: is_short_group = True elif self.minimum_duration is not None: if group.get_duration() < self.minimum_duration: is_short_group = True if is_short_group: start_dynamic = hairpin_token[0] #contexttools.DynamicMark(start_dynamic)(group[0]) command = marktools.LilyPondCommandMark(start_dynamic, 'right') attach(command, group[0]) else: descriptor = ' '.join([x for x in hairpin_token if x]) hairpin = spannertools.HairpinSpanner( descriptor=descriptor, include_rests=False, ) attach(hairpin, group) return expr
def __call__(self, divisions, seeds=None): r'''Call burnished rhythm-maker on `divisions`. Returns either list of tuplets or else list of note-lists. ''' duration_pairs, seeds = RhythmMaker.__call__(self, divisions, seeds) octuplet = self._prepare_input(seeds) talea, prolation_addenda = octuplet[:2] secondary_divisions = octuplet[-1] talee = (talea, prolation_addenda, secondary_divisions) result = self._scale_talee( duration_pairs, self.talea_denominator, talee) duration_pairs, lcd, talea, prolation_addenda, secondary_divisions = \ result secondary_duration_pairs = self._make_secondary_duration_pairs( duration_pairs, secondary_divisions) septuplet = (talea, prolation_addenda) + octuplet[2:-1] numeric_map = self._make_numeric_map( secondary_duration_pairs, septuplet) leaf_lists = self._make_leaf_lists(numeric_map, lcd) if not prolation_addenda: result = leaf_lists else: tuplets = self._make_tuplets(secondary_duration_pairs, leaf_lists) result = tuplets if self.beam_each_cell: for cell in result: beam = spannertools.MultipartBeamSpanner() attach(beam, cell) if self.tie_split_notes: self._add_ties(result) assert isinstance(result, list), repr(result) assert all(isinstance(x, selectiontools.Selection) for x in result) or \ all(isinstance(x, tuplettools.Tuplet) for x in result) return result
def p_leaf__leaf_body__post_events(self, p): r'''leaf : leaf_body post_events ''' p[0] = p[1] if p[2]: annotation = marktools.Annotation('post events', p[2]) attach(annotation, p[0])
def set_line_breaks_by_line_duration( expr, line_duration, line_break_class=None, kind='prolated', adjust_eol=False, add_empty_bars=False, ): r'''Iterate `line_break_class` instances in `expr` and accumulate `kind` duration. Add line break after every total less than or equal to `line_duration`. Set `line_break_class` to measure when `line_break_class` is none. ''' if line_break_class is None: line_break_class = measuretools.Measure prev = None cum_duration = durationtools.Duration(0) for cur in iterationtools.iterate_components_in_expr( expr, line_break_class): # compress these 4 lines to only the 4th line after duration migration if kind == 'seconds': current_duration = cur._get_duration(in_seconds=True) elif kind == 'prolated': current_duration = cur._get_duration() elif kind == 'preprolated': current_duration = cur._preprolated_duration else: current_duration = getattr(cur._get_duration(), kind) candidate_duration = cum_duration + current_duration if candidate_duration < line_duration: cum_duration += current_duration elif candidate_duration == line_duration: command = marktools.LilyPondCommandMark('break', 'closing') attach(command, cur) if adjust_eol: marktools.LilyPondCommandMark( 'adjustEOLTimeSignatureBarlineExtraOffset', 'closing')(cur) if add_empty_bars: if cur.bar_line.kind is None: cur.bar_line.kind = '' cum_duration = durationtools.Duration(0) else: if prev is not None: command = marktools.LilyPondCommandMark('break', 'closing') attach(command, prev) if adjust_eol: marktools.LilyPondCommandMark( 'adjustEOLTimeSignatureBarlineExtraOffset', 'closing')(prev) if add_empty_bars: if cur.bar_line.kind is None: cur.bar_line.kind = '' cum_duration = current_duration prev = cur
def execute_against_score(self, score): r'''Execute mark set expression against `score`. ''' mark = self.source_expression.payload assert isinstance(mark, marktools.Mark), repr(mark) for leaf in self._iterate_selected_leaves_in_score(score): new_mark = copy.deepcopy(mark) attach(new_mark, leaf)
def execute_against_score(self, score): r'''Execute dynamic set expression against `score`. ''' dynamic_mark = self.source_expression.payload for leaf in self._iterate_selected_leaves_in_score(score): for mark in leaf._get_marks(contexttools.DynamicMark): mark.detach() dynamic = contexttools.DynamicMark(dynamic_mark) attach(dynamic, leaf)
def make_dynamic_spanner_below_with_nib_at_right( dynamic_text, components=None, ): r'''Span `components` with text spanner. Position spanner below staff and configure with `dynamic_text`, solid line and upward-pointing nib at right: :: >>> staff = Staff("c'8 d'8 e'8 f'8") :: >>> spannertools.make_dynamic_spanner_below_with_nib_at_right( ... 'mp', staff[:]) TextSpanner(c'8, d'8, e'8, f'8) .. doctest:: >>> f(staff) \new Staff { \override TextSpanner #'bound-details #'left #'text = \markup { \dynamic { mp } } \override TextSpanner #'bound-details #'right #'text = \markup { \draw-line #'(0 . 1) } \override TextSpanner #'bound-details #'right-broken #'text = ##f \override TextSpanner #'dash-fraction = #1 \override TextSpanner #'direction = #down c'8 \startTextSpan d'8 e'8 f'8 \stopTextSpan \revert TextSpanner #'bound-details \revert TextSpanner #'dash-fraction \revert TextSpanner #'direction } :: >>> show(staff) # doctest: +SKIP Returns spanner. ''' from abjad.tools import spannertools from abjad.tools.scoretools import attach text_spanner = spannertools.TextSpanner() attach(text_spanner, components) text_spanner._dynamic_text = dynamic_text dynamic_text = markuptools.Markup(r'\dynamic { %s }' % dynamic_text) text_spanner.override.text_spanner.bound_details__left__text = dynamic_text right_text = markuptools.Markup(markuptools.MarkupCommand('draw-line', schemetools.SchemePair(0, 1))) text_spanner.override.text_spanner.bound_details__right__text = right_text text_spanner.override.text_spanner.bound_details__right_broken__text = False text_spanner.override.text_spanner.dash_fraction = 1 text_spanner.override.text_spanner.direction = Down return text_spanner
def add_double_bar(self): r'''Add double bar to end of score. >>> staff = Staff("c'4 d'4 e'4 f'4") >>> score = Score([staff]) .. doctest:: >>> f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 } >> :: >>> show(score) # doctest: +SKIP :: >>> score.add_double_bar() BarLine('|.')(f'4) .. doctest:: >>> f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 \bar "|." } >> :: >>> show(score) # doctest: +SKIP Returns bar line. ''' from abjad.tools import leaftools from abjad.tools import marktools from abjad.tools import selectiontools from abjad.tools.scoretools import attach selection = selectiontools.select(self) last_leaf = selection._get_component(leaftools.Leaf, -1) double_bar = marktools.BarLine('|.') attach(double_bar, last_leaf) return double_bar
def _add_or_remove_notes_to_achieve_written_duration(self, new_written_duration): from abjad.tools import scoretools from abjad.tools import notetools from abjad.tools import spannertools from abjad.tools import tuplettools from abjad.tools.scoretools import attach new_written_duration = durationtools.Duration(new_written_duration) if new_written_duration.is_assignable: self[0].written_duration = new_written_duration for leaf in self[1:]: parent = leaf._parent if parent: index = parent.index(leaf) del (parent[index]) first = self[0] for spanner in first._get_spanners(spannertools.TieSpanner): spanner.detach() elif new_written_duration.has_power_of_two_denominator: durations = notetools.make_notes(0, [new_written_duration]) for leaf, token in zip(self, durations): leaf.written_duration = token.written_duration if len(self) == len(durations): pass elif len(durations) < len(self): for leaf in self[len(durations) :]: parent = leaf._parent if parent: index = parent.index(leaf) del (parent[index]) elif len(self) < len(durations): for spanner in self[0]._get_spanners(spannertools.TieSpanner): spanner.detach() difference = len(durations) - len(self) extra_leaves = self[0] * difference for extra_leaf in extra_leaves: for spanner in extra_leaf._get_spanners(): spanner._remove(extra_leaf) extra_tokens = durations[len(self) :] for leaf, token in zip(extra_leaves, extra_tokens): leaf.written_duration = token.written_duration ties = self[-1]._get_spanners(spannertools.TieSpanner) if not ties: tie = spannertools.TieSpanner() attach(tie, list(self)) self[-1]._splice(extra_leaves, grow_spanners=True) else: durations = notetools.make_notes(0, new_written_duration) assert isinstance(durations[0], tuplettools.Tuplet) fmtuplet = durations[0] new_chain_written = fmtuplet[0]._get_tie_chain()._preprolated_duration self._add_or_remove_notes_to_achieve_written_duration(new_chain_written) multiplier = fmtuplet.multiplier tuplettools.Tuplet(multiplier, self.leaves) return self[0]._get_tie_chain()
def __init__(self, time_signature, music=None, **kwargs): from abjad.tools.scoretools import attach # set time signature adjustment indicator before # contents initialization self._automatically_adjust_time_signature = False FixedDurationContainer.__init__(self, time_signature, music) self._always_format_time_signature = False self._measure_number = None time_signature = contexttools.TimeSignatureMark(time_signature) attach(time_signature, self) self._initialize_keyword_values(**kwargs)
def _process_post_events(self, leaf, post_events): for post_event in post_events: if hasattr(post_event, "_attach"): attach(post_event, leaf) else: annotation = [x for x in leaf._get_marks(marktools.Annotation) if x.name == "spanners"] if not annotation: annotation = marktools.Annotation("spanners", []) attach(annotation, leaf) else: annotation = annotation[0] annotation.value.append(post_event)
def execute_against_score(self, score): r'''Execute articulation set expression against `score`. ''' articulation_list = self.source_expression.payload leaves = self._iterate_selected_leaves_in_score(score) articulation_list = [ marktools.Articulation(x) for x in articulation_list ] for leaf in leaves: for articulation in articulation_list: new_articulation = copy.copy(articulation) attach(new_articulation, leaf)
def _conditionally_adjust_time_signature(self, old_denominator): from abjad.tools.scoretools import attach if self.automatically_adjust_time_signature: naive_time_signature = self._preprolated_duration better_time_signature = \ mathtools.NonreducedFraction(naive_time_signature) better_time_signature = \ better_time_signature.with_denominator(old_denominator) better_time_signature = \ contexttools.TimeSignatureMark(better_time_signature) for mark in self._get_marks(contexttools.TimeSignatureMark): mark.detach() attach(better_time_signature, self)
def _make_container(self, division): numerator, denominator = division # eventually allow for non-power-of-two divisions assert mathtools.is_positive_integer_power_of_two(denominator) denominator_multiplier = 2 ** self.denominator_multiplier_exponent denominator *= denominator_multiplier unit_duration = durationtools.Duration(1, denominator) numerator *= denominator_multiplier notes = notetools.make_notes(numerator * [0], [unit_duration]) container = containertools.Container(notes) if self.beam_each_cell: beam = spannertools.BeamSpanner() attach(beam, container) return container
def execute_against_score(self, score): r'''Execute spanner set expression against `score`. ''' spanner = self.source_expression.payload assert isinstance(spanner, spannertools.Spanner), repr(spanner) result = self.target_counttime_component_select_expression.evaluate_against_score(score) if isinstance(result, list): for element in result: leaves = element.payload new_spanner = copy.copy(spanner) attach(new_spanner, leaves) else: leaves = result.payload new_spanner = copy.copy(spanner) attach(new_spanner, leaves)
def _copy_leaf_type_and_pitches(self, leaf_one, leaf_two): index = leaf_two._get_parentage().parent.index(leaf_two) duration = leaf_two.written_duration if isinstance(leaf_one, notetools.Note): new_leaf = notetools.Note(leaf_one.written_pitch, duration) elif isinstance(leaf_one, scoretools.Chord): new_leaf = scoretools.Chord(leaf_one.written_pitches, duration) else: new_leaf = resttools.Rest(duration) tempo_marks = leaf_two._get_marks(contexttools.TempoMark) if tempo_marks: tempo = tempo_marks[0] attach(tempo, new_leaf) leaf_two._get_parentage().parent[index] = new_leaf return new_leaf
def label_leaves_in_expr_with_numbered_inversion_equivalent_interval_classes(expr, markup_direction=Up): r"""Label leaves in `expr` with numbered inversion-equivalent interval classes: :: >>> notes = notetools.make_notes([0, 25, 11, -4, -14, -13, 9, 10, 6, 5], [Duration(1, 8)]) >>> staff = Staff(notes) >>> labeltools.label_leaves_in_expr_with_numbered_inversion_equivalent_interval_classes( ... staff) .. doctest:: >>> f(staff) \new Staff { c'8 ^ \markup { 1 } cs'''8 ^ \markup { 2 } b'8 ^ \markup { 3 } af8 ^ \markup { 2 } bf,8 ^ \markup { 1 } b,8 ^ \markup { 2 } a'8 ^ \markup { 1 } bf'8 ^ \markup { 4 } fs'8 ^ \markup { 1 } f'8 } :: >>> show(staff) # doctest: +SKIP Returns none. """ for note in iterationtools.iterate_notes_in_expr(expr): logical_voice_iterator = \ iterationtools.iterate_logical_voice_from_component( note, leaftools.Leaf) try: logical_voice_iterator.next() next_leaf = logical_voice_iterator.next() if isinstance(next_leaf, notetools.Note): mdi = note.written_pitch - next_leaf.written_pitch iecic = \ pitchtools.NumberedInversionEquivalentIntervalClass(mdi) markup = markuptools.Markup(iecic, markup_direction) attach(markup, note) except StopIteration: pass
def _set_duration(self, new_duration): from abjad.tools import leaftools from abjad.tools import notetools from abjad.tools import spannertools from abjad.tools import tuplettools from abjad.tools.scoretools import attach new_duration = durationtools.Duration(new_duration) # change LilyPond multiplier if leaf already has LilyPond multiplier if self.lilypond_duration_multiplier is not None: multiplier = new_duration / self.written_duration self.lilypond_duration_multiplier = multiplier return [self] # change written duration if new duration is assignable try: self.written_duration = new_duration return [self] except AssignabilityError: pass # make new notes or tuplets if new duration is nonassignable components = notetools.make_notes(0, new_duration) if isinstance(components[0], leaftools.Leaf): tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for x, component in zip(all_leaves, components): x.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) parentage = self._get_parentage() if not parentage._get_spanners(spannertools.TieSpanner): tie = spannertools.TieSpanner() attach(tie, all_leaves) return all_leaves else: assert isinstance(components[0], tuplettools.Tuplet) tuplet = components[0] components = tuplet[:] tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for x, component in zip(all_leaves, components): x.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) if not self._get_spanners(spannertools.TieSpanner): tie = spannertools.TieSpanner() attach(tie, all_leaves) tuplet_multiplier = tuplet.multiplier tuplettools.Tuplet(tuplet_multiplier, all_leaves) return [tuplet]
def __call__(self, beatspan): result = self.root_node(beatspan) result_leaves = [] for x in result: if isinstance(x, containertools.Container): result_leaves.extend(x.select_leaves()) else: result_leaves.append(x) for result_leaf, q_grid_leaf in zip(result_leaves, self.leaves[:-1]): if q_grid_leaf.q_event_proxies: q_events = [q_event_proxy.q_event for q_event_proxy in q_grid_leaf.q_event_proxies] q_events.sort(key=lambda x: x.index) annotation = marktools.Annotation('q_events', tuple(q_events)) attach(annotation, result_leaf) return result