示例#1
0
 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
示例#2
0
 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
示例#3
0
 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
示例#4
0
 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
示例#5
0
    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,
        )
示例#6
0
    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
示例#7
0
    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
示例#9
0
 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
示例#12
0
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,
            )