def _rewrite_meter_( selections, meters, reference_meters=None, rewrite_tuplets=False, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools.topleveltools import mutate meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] reference_meters = reference_meters or () selections = DurationSpellingSpecifier._split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=use_messiaen_style_ties, ) measures = scoretools.make_spacer_skip_measures(durations) staff = scoretools.Staff(measures) mutate(staff).replace_measure_contents(selections) for measure, meter in zip(staff, meters): for reference_meter in reference_meters: if str(reference_meter) == str(meter): meter = reference_meter break mutate(measure[:]).rewrite_meter( meter, rewrite_tuplets=rewrite_tuplets, use_messiaen_style_ties=use_messiaen_style_ties, ) selections = [] for measure in staff: selections.append(measure[:]) return selections
def _make_music(self, divisions, seeds): from abjad.tools import rhythmmakertools selections = [] duration_specifier = self.duration_spelling_specifier if duration_specifier is None: duration_specifier = rhythmmakertools.DurationSpellingSpecifier() tuplet_specifier = self.tuplet_spelling_specifier if tuplet_specifier is None: tuplet_specifier = rhythmmakertools.TupletSpellingSpecifier() for division in divisions: if (duration_specifier.spell_metrically == True or (duration_specifier.spell_metrically == 'unassignable' and not mathtools.is_assignable_integer(division.numerator))): meter = metertools.Meter(division) rhythm_tree_container = meter.root_node durations = [_.duration for _ in rhythm_tree_container] else: durations = [division] selection = scoretools.make_leaves( pitches=0, durations=durations, decrease_durations_monotonically=\ duration_specifier.decrease_durations_monotonically, forbidden_written_duration=\ duration_specifier.forbidden_written_duration, is_diminution=tuplet_specifier.is_diminution, ) selections.append(selection) selections = self._apply_burnish_specifier(selections) self._apply_beam_specifier(selections) selections = self._apply_output_masks(selections) return selections
def _split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools.topleveltools import inspect_ from abjad.tools.topleveltools import mutate meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] music = sequencetools.flatten_sequence(selections) assert isinstance(music, list), repr(music) total_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in music) assert total_duration == music_duration voice = scoretools.Voice(music) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) selections = list(voice[:]) return selections
def __init__( self, kernel_denominator=32, maximum_repetitions=None, meters=None, offset_counter=None, ): from abjad.tools import metertools self._cached_offset_counters = {} if maximum_repetitions is not None: maximum_repetitions = int(maximum_repetitions) assert 0 < maximum_repetitions self._maximum_repetitions = maximum_repetitions if offset_counter: self._offset_counter = \ metertools.MetricAccentKernel.count_offsets_in_expr( offset_counter) else: self._offset_counter = {} self._ordered_offsets = tuple(sorted(self.offset_counter)) meters = meters or () self._meters = tuple(metertools.Meter(_) for _ in meters) self._kernel_denominator = durationtools.Duration(kernel_denominator) self._kernels = {} for meter in self._meters: kernel = meter.generate_offset_kernel_to_denominator( self._kernel_denominator) self._kernels[kernel] = meter if self.kernels: self._longest_kernel = sorted( self._kernels, key=lambda x: x.duration, )[-1] else: self._longest_kernel = None
def __call__(self, expr): r'''Calls measurewise attack-point optimizer. Returns none. ''' assert isinstance(expr, scoretools.Measure) meter = metertools.Meter(expr) mutate(expr[:]).rewrite_meter( meter, boundary_depth=1, )
def __call__(self, divisions=None): r'''Calls beat division maker on `divisions`. .. container:: example **Example 1.** Calls maker on nonempty input: :: >>> maker = makertools.BeatDivisionMaker( ... depths=[1], ... ) >>> lists = maker([(7, 4), (6, 4)]) >>> for list_ in lists: ... list_ [Division(3, 4), Division(2, 4), Division(2, 4)] [Division(3, 4), Division(3, 4)] Returns list of division lists. .. container:: example **Example 2.** Calls maker on empty input: :: >>> maker = makertools.BeatDivisionMaker( ... depths=[1], ... ) >>> lists = maker([]) >>> lists [] Returns empty list. Returns (possibly empty) list of division lists. ''' input_divisions = divisions or [] if not input_divisions: return [] output_division_lists = [] depths = self._get_depths() for i, input_division in enumerate(input_divisions): input_division = durationtools.Division(input_division) depth = depths[i] meter = metertools.Meter(input_division) durations = meter.get_durations_at_depth(depth) denominator = input_division.denominator output_division_list = [ durationtools.Division(_.with_denominator(denominator)) for _ in durations ] output_division_lists.append(output_division_list) return output_division_lists
def from_meter(meter, denominator=32, normalize=True): r'''Create a metric accent kernel from `meter`. Returns new metric accent kernel. ''' from abjad.tools import metertools if not isinstance(meter, metertools.Meter): meter = metertools.Meter(meter) return meter.generate_offset_kernel_to_denominator( denominator=denominator, normalize=normalize, )
def _split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools.topleveltools import inspect_ from abjad.tools.topleveltools import mutate from abjad.tools.topleveltools import select meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] selections = sequencetools.flatten_sequence(selections) assert isinstance(selections, list), repr(selections) meter_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in selections) if not meter_duration == music_duration: message = 'Duration of meters is {!s}' message += ' but duration of selections is {!s}:' message = message.format(meter_duration, music_duration) message += '\nmeters: {}.'.format(meters) message += '\nmusic: {}.'.format(selections) raise Exception(message) voice = scoretools.Voice(selections) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) #raise Exception(voice) #selections = list(voice[:]) #return selections components = mutate(voice).eject_contents() component_durations = [inspect_(_).get_duration() for _ in components] parts = sequencetools.partition_sequence_by_weights( component_durations, weights=durations, allow_part_weights=Exact, ) part_lengths = [len(_) for _ in parts] parts = sequencetools.partition_sequence_by_counts( components, counts=part_lengths, overhang=Exact, ) selections = [select(_) for _ in parts] return selections
def _make_music(self, divisions, rotation): from abjad.tools import rhythmmakertools selections = [] duration_specifier = self._get_duration_spelling_specifier() tie_specifier = self._get_tie_specifier() tuplet_specifier = self._get_tuplet_spelling_specifier() for division in divisions: if (duration_specifier.spell_metrically == True or (duration_specifier.spell_metrically == 'unassignable' and not mathtools.is_assignable_integer(division.numerator))): meter = metertools.Meter(division) rhythm_tree_container = meter.root_node durations = [_.duration for _ in rhythm_tree_container] elif isinstance(duration_specifier.spell_metrically, rhythmmakertools.PartitionTable): partition_table = duration_specifier.spell_metrically durations = partition_table.respell_division(division) else: durations = [division] selection = scoretools.make_leaves( pitches=0, durations=durations, decrease_durations_monotonically=\ duration_specifier.decrease_durations_monotonically, forbidden_written_duration=\ duration_specifier.forbidden_written_duration, is_diminution=tuplet_specifier.is_diminution, use_messiaen_style_ties=tie_specifier.use_messiaen_style_ties, ) if (1 < len(selection) and not selection[0]._has_spanner(spannertools.Tie)): tie = spannertools.Tie(use_messiaen_style_ties=tie_specifier. use_messiaen_style_ties, ) attach(tie, selection[:]) selections.append(selection) selections = self._apply_burnish_specifier(selections) beam_specifier = self._get_beam_specifier() beam_specifier(selections) selections = self._apply_division_masks(selections, rotation) if duration_specifier.rewrite_meter: selections = duration_specifier._rewrite_meter_( selections, divisions, use_messiaen_style_ties=tie_specifier.use_messiaen_style_ties, ) return selections
def __call__(self, divisions=None): r'''Calls division-maker on `divisions`. .. container:: example **Example 1.** NonreducedFraction without remainder: :: >>> maker = makertools.SplitByDurationsDivisionCallback( ... cyclic=True, ... durations=[(1, 4)], ... ) :: >>> time_signatures = [(3, 4)] >>> division_lists = maker(time_signatures) >>> for division_list in division_lists: ... division_list [NonreducedFraction(1, 4), NonreducedFraction(1, 4), NonreducedFraction(1, 4)] :: >>> maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=time_signatures, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { { \time 3/4 c'4 c'4 c'4 } } .. container:: example **Example 2.** NonreducedFraction with remainder: :: >>> maker = makertools.SplitByDurationsDivisionCallback( ... durations=[(1, 4)], ... ) :: >>> time_signatures = [(7, 8)] >>> division_lists = maker(time_signatures) >>> for division_list in division_lists: ... division_list [NonreducedFraction(1, 4), NonreducedFraction(1, 4), NonreducedFraction(1, 4), NonreducedFraction(1, 8)] :: >>> maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=time_signatures, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { { \time 7/8 c'4 c'4 c'4 c'8 } } Positions remainder at right of output because divison-maker `remainder` defaults to right. .. container:: example **Example 3.** Multiple divisions: :: >>> maker = makertools.SplitByDurationsDivisionCallback( ... cyclic=True, ... durations=[(1, 4)], ... ) :: >>> time_signatures = [(2, 4), (3, 4)] >>> division_lists = maker(time_signatures) >>> for division_list in division_lists: ... division_list [NonreducedFraction(1, 4), NonreducedFraction(1, 4)] [NonreducedFraction(1, 4), NonreducedFraction(1, 4), NonreducedFraction(1, 4)] :: >>> maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=time_signatures, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { { \time 2/4 c'4 c'4 } { \time 3/4 c'4 c'4 c'4 } } .. container:: example **Example 4.** No durations: :: >>> maker = makertools.SplitByDurationsDivisionCallback() :: >>> time_signatures = [(6, 32)] >>> division_lists = maker(time_signatures) >>> for division_list in division_lists: ... division_list [NonreducedFraction(6, 32)] :: >>> maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=time_signatures, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { { \time 6/32 c'8. } } Returns input division unchanged. .. container:: example **Example 5.** Empty input: :: >>> maker = makertools.SplitByDurationsDivisionCallback(durations=[(1, 4)]) >>> maker() [] Returns empty list. Returns possibly empty list of division lists. ''' divisions = divisions or [] if not divisions: return divisions division_lists = [] for i, division in enumerate(divisions): input_division = mathtools.NonreducedFraction(division) input_duration = durationtools.Duration(input_division) input_meter = metertools.Meter(input_division) assert 0 < input_division, repr(input_division) if not self.durations: division_list = [input_division] division_lists.append(division_list) continue if input_meter.is_simple or not self.durations: durations = self.durations[:] elif input_meter.is_compound: multiplier = self.compound_meter_multiplier durations = [ mathtools.NonreducedFraction(multiplier * _) for _ in self.durations ] #division_list = list(self.durations) division_list = list(durations) pattern_rotation_index = self.pattern_rotation_index or 0 pattern_rotation_index *= i division_list = sequencetools.rotate_sequence( division_list, pattern_rotation_index, ) if self.cyclic: division_list = sequencetools.repeat_sequence_to_weight( division_list, input_division, allow_total=Less, ) total_duration = durationtools.Duration(sum(division_list)) if total_duration == input_duration: division_lists.append(division_list) continue if self.remainder is None: message = 'can not fill {} from {} exactly.' #message = message.format(input_division, self.durations) message = message.format(input_division, durations) raise Exception(message) remainder = input_division - total_duration remainder = durationtools.Duration(remainder) remainder = mathtools.NonreducedFraction(remainder) if self.remainder == Left: if self.remainder_fuse_threshold is None: division_list.insert(0, remainder) elif remainder <= self.remainder_fuse_threshold: fused_value = division_list[0] + remainder fused_value = mathtools.NonreducedFraction(fused_value) division_list[0] = fused_value else: division_list.insert(0, remainder) elif self.remainder == Right: if self.remainder_fuse_threshold is None: division_list.append(remainder) elif remainder <= self.remainder_fuse_threshold: fused_value = division_list[-1] + remainder fused_value = mathtools.NonreducedFraction(fused_value) division_list[-1] = fused_value else: division_list.append(remainder) else: raise ValueError((self.remainder, remainder)) total_duration = durationtools.Duration(sum(division_list)) pair = total_duration, input_duration assert total_duration == input_duration, pair division_lists.append(division_list) for _ in division_lists: assert isinstance(_, list), repr(_) return division_lists
def make_leaves_from_talea( talea, talea_denominator, decrease_durations_monotonically=True, forbidden_written_duration=None, spell_metrically=None, use_messiaen_style_ties=False, ): r'''Makes leaves from `talea`. Interprets positive elements in `talea` as notes numerators. Interprets negative elements in `talea` as rests numerators. Sets the pitch of all notes to middle C. .. container:: example **Example 1.** Makes leaves from talea: :: >>> leaves = scoretools.make_leaves_from_talea([3, -3, 5, -5], 16) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> time_signature = TimeSignature((4, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { \time 4/4 c'8. r8. c'4 ~ c'16 r4 r16 } .. container:: example **Example 2.** Increases durations monotonically: :: >>> leaves = scoretools.make_leaves_from_talea( ... [3, -3, 5, -5], 16, ... decrease_durations_monotonically=False, ... ) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> time_signature = TimeSignature((4, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { \time 4/4 c'8. r8. c'16 ~ c'4 r16 r4 } .. container:: example **Example 3.** Forbids written durations greater than or equal to a half note: :: >>> leaves = scoretools.make_leaves_from_talea( ... [3, -3, 5, -5], 16, ... forbidden_written_duration=Duration(1, 4), ... ) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> time_signature = TimeSignature((4, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { \time 4/4 c'8. r8. c'8 ~ c'8 ~ c'16 r8 r8 r16 } .. container:: example **Example 4.** Spells unassignable durations metrically: :: >>> leaves = scoretools.make_leaves_from_talea( ... [3, -3, 5, -5], 16, ... spell_metrically='unassignable', ... ) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> time_signature = TimeSignature((4, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { \time 4/4 c'8. r8. c'8. ~ c'8 r8. r8 } .. container:: example **Example 5.** Uses Messiaen-style ties: :: >>> leaves = scoretools.make_leaves_from_talea( ... [5, 9], 8, ... spell_metrically='unassignable', ... use_messiaen_style_ties=True, ... ) >>> staff = Staff(leaves) >>> staff.context_name = 'RhythmicStaff' >>> time_signature = TimeSignature((4, 4)) >>> attach(time_signature, staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new RhythmicStaff { \time 4/4 c'4. c'4 \repeatTie c'4. c'4. \repeatTie c'4. \repeatTie } Returns selection. ''' from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import spannertools assert all(x != 0 for x in talea), repr(talea) result = [] for note_value in talea: if 0 < note_value: pitches = [0] else: pitches = [None] division = durationtools.Duration( abs(note_value), talea_denominator, ) if (spell_metrically is True or (spell_metrically == 'unassignable' and not mathtools.is_assignable_integer(division.numerator))): meter = metertools.Meter(division) rhythm_tree_container = meter.root_node durations = [_.duration for _ in rhythm_tree_container] else: durations = [division] leaves = scoretools.make_leaves( pitches, durations, decrease_durations_monotonically=decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_messiaen_style_ties=use_messiaen_style_ties, ) if (1 < len(leaves) and not leaves[0]._has_spanner(spannertools.Tie) and not isinstance(leaves[0], scoretools.Rest)): tie = spannertools.Tie( use_messiaen_style_ties=use_messiaen_style_ties, ) attach(tie, leaves[:]) result.extend(leaves) result = selectiontools.Selection(result) return result
def _rewrite_meter( components, meter, boundary_depth=None, initial_offset=None, maximum_dot_count=None, rewrite_tuplets=True, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools assert isinstance(components, selectiontools.Selection), \ repr(components) if not isinstance(meter, metertools.Meter): meter = metertools.Meter(meter) boundary_depth = boundary_depth or meter.preferred_boundary_depth def recurse( boundary_depth=None, boundary_offsets=None, depth=0, logical_tie=None, ): offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) #print('DEPTH:', depth) logical_tie_duration = logical_tie._preprolated_duration logical_tie_timespan = logical_tie.get_timespan() logical_tie_start_offset = logical_tie_timespan.start_offset logical_tie_stop_offset = logical_tie_timespan.stop_offset logical_tie_starts_in_offsets = logical_tie_start_offset in offsets logical_tie_stops_in_offsets = logical_tie_stop_offset in offsets if not metertools.MeterManager.is_acceptable_logical_tie( logical_tie_duration=logical_tie_duration, logical_tie_starts_in_offsets=logical_tie_starts_in_offsets, logical_tie_stops_in_offsets=logical_tie_stops_in_offsets, maximum_dot_count=maximum_dot_count, ): #print('UNACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) split_offset = None offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) # If the logical tie's start aligns, take the latest possible offset. if logical_tie_starts_in_offsets: offsets = reversed(offsets) for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break #print('\tABS:', split_offset) if split_offset is not None: split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print() recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth + 1, logical_tie=logical_tie, ) elif metertools.MeterManager.is_boundary_crossing_logical_tie( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, logical_tie_start_offset=logical_tie_start_offset, logical_tie_stop_offset=logical_tie_stop_offset, ): #print('BOUNDARY CROSSING', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) offsets = boundary_offsets if logical_tie_start_offset in boundary_offsets: offsets = reversed(boundary_offsets) split_offset = None for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break assert split_offset is not None #print('\tABS:', split_offset) split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print('ACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) #print() logical_tie[:]._fuse() # Validate arguments. assert Selection._all_are_contiguous_components_in_same_logical_voice( components) if not isinstance(meter, metertools.Meter): meter = \ metertools.Meter(meter) #assert sum([x._preprolated_duration for x in components]) == \ # meter.preprolated_duration if boundary_depth is not None: boundary_depth = int(boundary_depth) if maximum_dot_count is not None: maximum_dot_count = int(maximum_dot_count) assert 0 <= maximum_dot_count if initial_offset is None: initial_offset = durationtools.Offset(0) initial_offset = durationtools.Offset(initial_offset) first_start_offset = inspect_(components[0]).get_timespan().start_offset last_start_offset = inspect_(components[-1]).get_timespan().start_offset difference = last_start_offset - first_start_offset + initial_offset assert difference < meter.implied_time_signature.duration # Build offset inventory, adjusted for initial offset and prolation. first_offset = components[0]._get_timespan().start_offset first_offset -= initial_offset prolation = components[0]._get_parentage(include_self=False).prolation offset_inventory = [] for offsets in meter.depthwise_offset_inventory: offsets = [(x * prolation) + first_offset for x in offsets] offset_inventory.append(tuple(offsets)) # Build boundary offset inventory, if applicable. if boundary_depth is not None: boundary_offsets = offset_inventory[boundary_depth] else: boundary_offsets = None # Cache results of iterator, as we'll be mutating the underlying collection iterator = metertools.MeterManager.iterate_rewrite_inputs(components) items = tuple(iterator) for item in items: if isinstance(item, selectiontools.LogicalTie): #print('RECURSING:', item) recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=0, logical_tie=item, ) elif isinstance(item, scoretools.Tuplet) and rewrite_tuplets == False: pass else: #print('DESCENDING:', item) preprolated_duration = sum([x._preprolated_duration for x in item]) if preprolated_duration.numerator == 1: preprolated_duration = mathtools.NonreducedFraction( preprolated_duration) preprolated_duration = preprolated_duration.with_denominator( preprolated_duration.denominator * 4) sub_metrical_hierarchy = metertools.Meter(preprolated_duration) sub_boundary_depth = 1 if boundary_depth is None: sub_boundary_depth = None _rewrite_meter( item[:], sub_metrical_hierarchy, boundary_depth=sub_boundary_depth, maximum_dot_count=maximum_dot_count, )