def _fuse_tuplets(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_parent( self, prototype=(scoretools.Tuplet, )) if len(self) == 0: return None first = self[0] first_multiplier = first.multiplier first_type = type(first) for tuplet in self[1:]: if tuplet.multiplier != first_multiplier: message = 'tuplets must carry same multiplier.' raise ValueError(message) if type(tuplet) != first_type: message = 'tuplets must be same type.' raise TypeError(message) if isinstance(first, scoretools.FixedDurationTuplet): total_contents_duration = sum([x._contents_duration for x in self]) new_target_duration = first_multiplier * total_contents_duration new_tuplet = scoretools.FixedDurationTuplet( new_target_duration, []) elif isinstance(first, scoretools.Tuplet): new_tuplet = scoretools.Tuplet(first_multiplier, []) else: message = 'unknown tuplet type.' raise TypeError(message) wrapped = False if self[0]._get_parentage().root is not \ self[-1]._get_parentage().root: dummy_container = scoretools.Container(self) wrapped = True mutate(self).swap(new_tuplet) if wrapped: del (dummy_container[:]) return new_tuplet
def _make_tuplets(self, divisions, leaf_lists): assert len(divisions) == len(leaf_lists) tuplets = [] for division, leaf_list in zip(divisions, leaf_lists): tuplet = scoretools.FixedDurationTuplet(division, leaf_list) tuplets.append(tuplet) return tuplets
def _remove_and_shrink_durated_parent_containers(self): from abjad.tools import indicatortools from abjad.tools import scoretools prolated_leaf_duration = self._get_duration() parentage = self._get_parentage(include_self=False) prolations = parentage._prolations current_prolation, i = durationtools.Duration(1), 0 parent = self._parent while parent is not None and not parent.is_simultaneous: current_prolation *= prolations[i] if isinstance(parent, scoretools.FixedDurationTuplet): candidate_new_parent_dur = ( parent.target_duration - current_prolation * self.written_duration) if durationtools.Duration(0) < candidate_new_parent_dur: parent.target_duration = candidate_new_parent_dur elif isinstance(parent, scoretools.Measure): indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator old_prolation = parent_time_signature.implied_prolation naive_time_signature = (parent_time_signature.duration - prolated_leaf_duration) better_time_signature = mathtools.NonreducedFraction( naive_time_signature) better_time_signature = better_time_signature.with_denominator( parent_time_signature.denominator) better_time_signature = indicatortools.TimeSignature( better_time_signature) detach(indicatortools.TimeSignature, parent) attach(better_time_signature, parent) indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator new_prolation = parent_time_signature.implied_prolation adjusted_prolation = old_prolation / new_prolation for x in parent: if isinstance(x, scoretools.FixedDurationTuplet): x.target_duration *= adjusted_prolation else: if adjusted_prolation != 1: new_target = \ x._preprolated_duration * adjusted_prolation scoretools.FixedDurationTuplet(new_target, [x]) parent = parent._parent i += 1 parentage = self._get_parentage(include_self=False) parent = self._parent if parent: index = parent.index(self) del (parent[index]) for x in parentage: if not len(x): x._extract() else: break
def _make_music(self, divisions, seeds): #assert not seeds, repr(seeds) if seeds is None: seeds = 0 selections = [] divisions = [durationtools.Division(_) for _ in divisions] denominators = datastructuretools.CyclicTuple(self.denominators) extra_counts_per_division = self.extra_counts_per_division or (0,) extra_counts_per_division = datastructuretools.CyclicTuple( extra_counts_per_division ) for i, division in enumerate(divisions, seeds): # not yet extended to work with non-power-of-two divisions assert mathtools.is_positive_integer_power_of_two( division.denominator), repr(division) denominator = denominators[i] extra_count = extra_counts_per_division[i] basic_duration = durationtools.Duration(1, denominator) unprolated_note_count = None if division < 2 * basic_duration: notes = scoretools.make_notes([0], [division]) else: unprolated_note_count = division / basic_duration unprolated_note_count = int(unprolated_note_count) unprolated_note_count = unprolated_note_count or 1 if 0 < extra_count: modulus = unprolated_note_count extra_count = extra_count % modulus elif extra_count < 0: modulus = int(math.ceil(unprolated_note_count / 2.0)) extra_count = abs(extra_count) % modulus extra_count *= -1 note_count = unprolated_note_count + extra_count durations = note_count * [basic_duration] notes = scoretools.make_notes([0], durations) assert all( _.written_duration.denominator == denominator for _ in notes ) tuplet_duration = durationtools.Duration(division) tuplet = scoretools.FixedDurationTuplet( duration=tuplet_duration, music=notes, ) if unprolated_note_count is not None: preferred_denominator = unprolated_note_count tuplet.preferred_denominator = preferred_denominator selection = selectiontools.Selection(tuplet) selections.append(selection) self._apply_beam_specifier(selections) return selections
def recurse(node, tuplet_duration): basic_prolated_duration = tuplet_duration / node._contents_duration basic_written_duration = \ basic_prolated_duration.equal_or_greater_power_of_two tuplet = scoretools.FixedDurationTuplet(tuplet_duration, []) for child in node.children: if isinstance(child, type(self)): tuplet.extend(recurse( child, child.preprolated_duration * basic_written_duration)) else: leaves = child(basic_written_duration) tuplet.extend(leaves) if 1 < len(leaves): tie = spannertools.Tie() attach(tie, leaves) if tuplet.multiplier == 1: return tuplet[:] return [tuplet]
def move_measure_prolation_to_full_measure_tuplet(expr): '''Move measure prolation to full-measure tuplet. Turn non-power-of-two measures into power-of-two measures containing a single fixed-duration tuplet. Note that not all non-power-of-two measures can be made power-of-two. Returns None because processes potentially many measures. ''' from abjad.tools import indicatortools from abjad.tools import scoretools for measure in iterate(expr).by_class(scoretools.Measure): effective_time_signature = measure.time_signature if effective_time_signature.has_non_power_of_two_denominator: # find time signature and contents multipliers time_signature_multiplier = effective_time_signature.implied_prolation contents_multiplier = \ measure._get_likely_multiplier_of_components(measure[:]) # update non-power-of-two time signature to power-of-two power_of_two_time_signature = effective_time_signature.with_power_of_two_denominator( contents_multiplier) detach(indicatortools.TimeSignature, measure) attach(power_of_two_time_signature, measure) # find target duration and create tuplet target_duration = time_signature_multiplier * measure._contents_duration tuplet = scoretools.FixedDurationTuplet(target_duration, measure[:]) # scale tuplet contents, if helpful if contents_multiplier is not None: numerator = contents_multiplier.numerator denominator = contents_multiplier.denominator pair = (denominator, numerator) inverse_multiplier = durationtools.Multiplier(*pair) tuplet._scale_contents(inverse_multiplier)
def _to_tuplet_with_ratio(self, proportions, is_diminution=True): from abjad.tools import scoretools # check input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self.written_duration # find basic duration of note in tuplet basic_prolated_duration = target_duration / sum(proportions.numbers) # find basic written duration of note in tuplet basic_written_duration = \ basic_prolated_duration.equal_or_greater_assignable # find written duration of each note in tuplet written_durations = [ _ * basic_written_duration for _ in proportions.numbers ] # make tuplet notes try: notes = [scoretools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [ durationtools.Duration(_, denominator) for _ in proportions.numbers ] notes = scoretools.make_notes(0, note_durations) # make tuplet tuplet = scoretools.FixedDurationTuplet(target_duration, notes) # fix tuplet contents if necessary tuplet._fix() # change prolation if necessary if not tuplet.multiplier == 1: if is_diminution: if not tuplet.is_diminution: tuplet.toggle_prolation() else: if tuplet.is_diminution: tuplet.toggle_prolation() # return tuplet return tuplet
def to_tuplet( self, proportions, dotted=False, is_diminution=True, ): r'''Change logical tie to tuplet. .. container:: example **Example 1.** Change logical tie to diminished tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=True) FixedDurationTuplet(Duration(3, 16), "c'8 c'16 c'16 c'16") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 3/5 { c'8 \< \p c'16 c'16 c'16 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP .. container:: example **Example 2.** Change logical tie to augmented tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=False) FixedDurationTuplet(Duration(3, 16), "c'16 c'32 c'32 c'32") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 6/5 { c'16 \< \p c'32 c'32 c'32 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP Returns tuplet. ''' from abjad.tools import scoretools from abjad.tools import mathtools from abjad.tools import agenttools from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools import scoretools # coerce input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self._preprolated_duration # find duration of each note in tuplet prolated_duration = target_duration / sum(proportions) # find written duration of each notes in tuplet if is_diminution: if dotted: basic_written_duration = \ prolated_duration.equal_or_greater_assignable else: basic_written_duration = \ prolated_duration.equal_or_greater_power_of_two else: if dotted: basic_written_duration = \ prolated_duration.equal_or_lesser_assignable else: basic_written_duration = \ prolated_duration.equal_or_lesser_power_of_two # find written duration of each note in tuplet written_durations = [x * basic_written_duration for x in proportions] # make tuplet notes try: notes = [scoretools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [durationtools.Duration(x, denominator) for x in proportions] notes = scoretools.make_notes(0, note_durations) # make tuplet tuplet = scoretools.FixedDurationTuplet(target_duration, notes) # replace logical tie with tuplet mutate(self).replace(tuplet) # untie tuplet for spanner in tuplet._get_spanners(spannertools.Tie): spanner._sever_all_components() #detach(spannertools.Tie, tuplet) # return tuplet return tuplet
def apply_full_measure_tuplets_to_contents_of_measures_in_expr( expr, supplement=None): r'''Applies full-measure tuplets to contents of measures in `expr`: :: >>> staff = Staff([ ... Measure((2, 8), "c'8 d'8"), ... Measure((3, 8), "e'8 f'8 g'8")]) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { { \time 2/8 c'8 d'8 } { \time 3/8 e'8 f'8 g'8 } } :: >>> scoretools.apply_full_measure_tuplets_to_contents_of_measures_in_expr(staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { { \time 2/8 { c'8 d'8 } } { \time 3/8 { e'8 f'8 g'8 } } } Returns none. ''' from abjad.tools import selectiontools from abjad.tools import scoretools supplement = selectiontools.Selection(supplement) assert isinstance(supplement, selectiontools.Selection) for measure in iterate(expr).by_class(scoretools.Measure): target_duration = measure._preprolated_duration tuplet = scoretools.FixedDurationTuplet(target_duration, measure[:]) if supplement: new_supplement = mutate(supplement).copy() tuplet.extend(new_supplement)