예제 #1
0
 def times(self, fraction, music):
     r'''Handles LilyPond ``\times`` command.
     '''
     n, d = fraction.numerator, fraction.denominator
     if not isinstance(music, scoretools.Context) and \
         not isinstance(music, scoretools.Leaf):
         return scoretools.Tuplet((n, d), music[:])
     return scoretools.Tuplet((n, d), [music])
예제 #2
0
 def times(self, fraction, music):
     r'''Handles LilyPond ``\times`` command.
     '''
     n, d = fraction.numerator, fraction.denominator
     if (not isinstance(music, scoretools.Context)
             and not isinstance(music, scoretools.Leaf)):
         assert isinstance(music, scoretools.Container), repr(music)
         leaves = music[:]
         music[:] = []
         return scoretools.Tuplet((n, d), leaves)
     return scoretools.Tuplet((n, d), [music])
예제 #3
0
 def _make_container(self, division):
     from abjad.tools import rhythmmakertools
     duration_spelling_specifier = self.duration_spelling_specifier
     if duration_spelling_specifier is None:
         duration_spelling_specifier = \
             rhythmmakertools.DurationSpellingSpecifier()
     forbidden_written_duration = \
         duration_spelling_specifier.forbidden_written_duration
     time_signature = indicatortools.TimeSignature(division)
     implied_prolation = time_signature.implied_prolation
     numerator, denominator = division.pair
     denominator = mathtools.greatest_power_of_two_less_equal(denominator)
     assert mathtools.is_positive_integer_power_of_two(denominator)
     exponent = self.exponent or 0
     denominator_multiplier = 2**exponent
     denominator *= denominator_multiplier
     unit_duration = durationtools.Duration(1, denominator)
     if forbidden_written_duration is not None:
         multiplier = 1
         while forbidden_written_duration <= unit_duration:
             unit_duration /= 2
             multiplier *= 2
         numerator *= multiplier
     numerator *= denominator_multiplier
     notes = scoretools.make_notes(numerator * [0], [unit_duration])
     if implied_prolation == 1:
         result = scoretools.Container(notes)
     else:
         multiplier = implied_prolation
         result = scoretools.Tuplet(multiplier, notes)
     return result
예제 #4
0
 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
예제 #5
0
    def to_fixed_multiplier(self):
        r'''Changes fixed-duration tuplet to (unqualified) tuplet.

        ..  container:: example

            ::

                >>> tuplet = scoretools.FixedDurationTuplet((2, 8), [])
                >>> tuplet.extend("c'8 d'8 e'8")
                >>> show(tuplet) # doctest: +SKIP

            ::

                >>> tuplet
                FixedDurationTuplet(Duration(1, 4), "c'8 d'8 e'8")

            ::

                >>> new_tuplet = tuplet.to_fixed_multiplier()
                >>> show(new_tuplet) # doctest: +SKIP

            ::

                >>> new_tuplet
                Tuplet(Multiplier(2, 3), "c'8 d'8 e'8")

        Returns new tuplet.
        '''
        from abjad.tools import scoretools
        new_tuplet = scoretools.Tuplet(self.multiplier, [])
        mutate(self).swap(new_tuplet)
        return new_tuplet
예제 #6
0
 def p_tuplet__FRACTION__container(self, p):
     r'''tuplet : FRACTION container
     '''
     assert isinstance(p[2], scoretools.Container)
     leaves = p[2][:]
     p[2][:] = []
     p[0] = scoretools.Tuplet(p[1], leaves)
예제 #7
0
 def _add_or_remove_notes_to_achieve_written_duration(
     self, new_written_duration):
     from abjad.tools import scoretools
     from abjad.tools import scoretools
     from abjad.tools import spannertools
     from abjad.tools import scoretools
     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.Tie):
             spanner._sever_all_components()
         #detach(spannertools.Tie, first)
     elif new_written_duration.has_power_of_two_denominator:
         durations = scoretools.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.Tie):
                 spanner._sever_all_components()
             #detach(spannertools.Tie, self[0])
             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.Tie)
             if not ties:
                 tie = spannertools.Tie()
                 attach(tie, list(self))
             self[-1]._splice(extra_leaves, grow_spanners=True)
     else:
         durations = scoretools.make_notes(0, new_written_duration)
         assert isinstance(durations[0], scoretools.Tuplet)
         fmtuplet = durations[0]
         new_logical_tie_written = \
             fmtuplet[0]._get_logical_tie()._preprolated_duration
         self._add_or_remove_notes_to_achieve_written_duration(
             new_logical_tie_written)
         multiplier = fmtuplet.multiplier
         scoretools.Tuplet(multiplier, self.leaves)
     return self[0]._get_logical_tie()
예제 #8
0
 def _set_duration(self, new_duration, use_messiaen_style_ties=False):
     from abjad.tools import scoretools
     from abjad.tools import spannertools
     new_duration = durationtools.Duration(new_duration)
     # change LilyPond multiplier if leaf already has LilyPond multiplier
     if self._get_indicators(durationtools.Multiplier):
         detach(durationtools.Multiplier, self)
         multiplier = new_duration.__div__(self.written_duration)
         attach(multiplier, self)
         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 = scoretools.make_notes(
         0,
         new_duration,
         use_messiaen_style_ties=use_messiaen_style_ties,
     )
     if isinstance(components[0], scoretools.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.Tie):
             #if spannertools.Tie._attachment_test(self):
             tie = spannertools.Tie()
             if tie._attachment_test(self):
                 tie = spannertools.Tie(
                     use_messiaen_style_ties=use_messiaen_style_ties, )
                 attach(tie, all_leaves)
         return all_leaves
     else:
         assert isinstance(components[0], scoretools.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.Tie):
             #if spannertools.Tie._attachment_test(self):
             tie = spannertools.Tie()
             if tie._attachment_test(self):
                 tie = spannertools.Tie(
                     use_messiaen_style_ties=use_messiaen_style_ties, )
                 attach(tie, all_leaves)
         tuplet_multiplier = tuplet.multiplier
         scoretools.Tuplet(tuplet_multiplier, all_leaves)
         return [tuplet]
예제 #9
0
파일: make_notes.py 프로젝트: odub/abjad
def make_notes(
    pitches, 
    durations, 
    decrease_durations_monotonically=True,
    use_messiaen_style_ties=False,
    ):
    r'''Makes notes according to `pitches` and `durations`.


    ..  container:: example

        **Example 1.** Cycles through `pitches` when the length of `pitches` is
        less than the length of `durations`:

        ::

            >>> notes = scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)])
            >>> notes
            Selection(Note("c'16"), Note("c'8"), Note("c'8"))
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16
                c'8
                c'8
            }

    ..  container:: example

        **Example 2.** Cycles through `durations` when the length of `durations`
        is less than the length of `pitches`:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0, 2, 4, 5, 7],
            ...     [(1, 16), (1, 8), (1, 8)],
            ...     )
            >>> notes
            Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8"))
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16
                d'8
                e'8
                f'16
                g'8
            }

    ..  container:: example

        **Example 3.** Creates ad hoc tuplets for nonassignable durations:

        ::

            >>> notes = scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)])
            >>> notes
            Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8"))
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16
                \tweak #'edge-height #'(0.7 . 0)
                \times 2/3 {
                    c'8
                }
                c'8
            }

    ..  container:: example

        **Example 4.** Set ``decrease_durations_monotonically=True`` to express
        tied values in decreasing duration:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     decrease_durations_monotonically=True,
            ...     )
            >>> notes
            Selection(Note("c'2."), Note("c'16"))
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2. ~
                c'16
            }

    ..  container:: example

        **Example 5.** Set ``decrease_durations_monotonically=False`` to
        express tied values in increasing duration:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> notes
            Selection(Note("c'16"), Note("c'2."))
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'16 ~
                c'2.
            }

    ..  container:: example

        **Example 6.** Uses Messiaen-style ties:

        ::

            >>> notes = scoretools.make_notes(
            ...     [0],
            ...     [(13, 16)],
            ...     use_messiaen_style_ties=True,
            ...     )
            >>> staff = Staff(notes)

        ::

            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2.
                c'16 \repeatTie
            }

    Set `pitches` to a single pitch or a sequence of pitches.

    Set `durations` to a single duration or a list of durations.

    Returns selection.
    '''
    from abjad.tools import scoretools
    from abjad.tools import selectiontools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions, 
        size,
        )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    durations = Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    def _make_unprolated_notes(
        pitches,
        durations,
        decrease_durations_monotonically=decrease_durations_monotonically,
        use_messiaen_style_ties=False,
        ):
        assert len(pitches) == len(durations)
        result = []
        for pitch, duration in zip(pitches, durations):
            result.extend(
                scoretools.make_tied_leaf(
                    scoretools.Note,
                    duration,
                    pitches=pitch,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                )
        return result

    result = []
    for duration in durations:
        # get factors in denominator of duration group duration not 1 or 2
        factors = set(mathtools.factors(duration[0].denominator))
        factors.discard(1)
        factors.discard(2)
        ps = pitches[0:len(duration)]
        pitches = pitches[len(duration):]
        if len(factors) == 0:
            result.extend(
                _make_unprolated_notes(
                    ps,
                    duration,
                    decrease_durations_monotonically=decrease_durations_monotonically,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                )
        else:
            # compute prolation
            denominator = duration[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / fractions.Fraction(*multiplier)
            duration = [ratio * durationtools.Duration(d) for d in duration]
            ns = _make_unprolated_notes(
                ps,
                duration,
                decrease_durations_monotonically=decrease_durations_monotonically,
                use_messiaen_style_ties=use_messiaen_style_ties,
                )
            t = scoretools.Tuplet(multiplier, ns)
            result.append(t)

    # return result
    result = selectiontools.Selection(result)
    return result
예제 #10
0
 def p_tuplet__FRACTION__container(self, p):
     r'''tuplet : FRACTION container
     '''
     p[0] = scoretools.Tuplet(p[1], p[2][:])
예제 #11
0
def make_leaves(
    pitches,
    durations,
    decrease_durations_monotonically=True,
    forbidden_written_duration=None,
    is_diminution=True,
    metrical_hiearchy=None,
    use_messiaen_style_ties=False,
    use_multimeasure_rests=False,
):
    r'''Makes leaves.

    ..  container:: example

        **Example 1.** Integer and string elements in `pitches` result in
        notes:

        ::

            >>> pitches = [2, 4, 'F#5', 'G#5']
            >>> duration = Duration(1, 4)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                d'4
                e'4
                fs''4
                gs''4
            }

    ..  container:: example

        **Example 2.** Tuple elements in `pitches` result in chords:

        ::

            >>> pitches = [(0, 2, 4), ('F#5', 'G#5', 'A#5')]
            >>> duration = Duration(1, 2)
            >>> leaves = scoretools.make_leaves(pitches, duration)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                <c' d' e'>2
                <fs'' gs'' as''>2
            }

    ..  container:: example

        **Example 3.** None-valued elements in `pitches` result in rests:

        ::

            >>> pitches = 4 * [None]
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new RhythmicStaff {
                r4
                r4
                r4
                r4
            }

    ..  container:: example

        **Example 4.** You can mix and match values passed to `pitches`:

        ::

            >>> pitches = [(0, 2, 4), None, 'C#5', 'D#5']
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                <c' d' e'>4
                r4
                cs''4
                ds''4
            }

    ..  container:: example

        **Example 5.** Read `pitches` cyclically when the length of `pitches`
        is less than the length of `durations`:

        ::

            >>> pitches = ['C5']
            >>> durations = 2 * [Duration(3, 8), Duration(1, 8)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c''4.
                c''8
                c''4.
                c''8
            }

    ..  container:: example

        **Example 6.** Read `durations` cyclically when the length of
        `durations` is less than the length of `pitches`:

        ::

            >>> pitches = "c'' d'' e'' f''"
            >>> durations = [Duration(1, 4)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c''4
                d''4
                e''4
                f''4
            }

    ..  container:: example

        **Example 7.** Elements in `durations` with non-power-of-two
        denominators result in tuplet-nested leaves:

        ::

            >>> pitches = ['D5']
            >>> durations = [Duration(1, 3), Duration(1, 3), Duration(1, 3)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \times 2/3 {
                    d''2
                    d''2
                    d''2
                }
            }

    ..  container:: example

        **Example 8.** Set `decrease_durations_monotonically` to true to
        return nonassignable durations tied from greatest to least:

        ::

            >>> pitches = ['D#5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(pitches, durations)
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 13/16
                ds''2. ~
                ds''16
            }

    ..  container:: example

        **Example 9.** Set `decrease_durations_monotonically` to false
        to return nonassignable durations tied from least to greatest:

        ::

            >>> pitches = ['E5']
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((13, 16))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 13/16
                e''16 ~
                e''2.
            }

    ..  container:: example

        **Example 10.** Set `forbidden_written_duration` to avoid notes
        greater than or equal to a certain written duration:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/4
                f'4 ~
                f'4 ~
                f'8
                g'4 ~
                g'4 ~
                g'8
            }

    ..  container:: example

        **Example 11.** You may set `forbidden_written_duration` and
        `decrease_durations_monotonically` together:

        ::

            >>> pitches = "f' g'"
            >>> durations = [Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     forbidden_written_duration=Duration(1, 2),
            ...     decrease_durations_monotonically=False,
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 4))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/4
                f'8 ~
                f'4 ~
                f'4
                g'8 ~
                g'4 ~
                g'4
            }

    ..  container:: example

        **Example 12.** Set `is_diminution` to true to produce
        diminished tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=True
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/14
                \tweak #'edge-height #'(0.7 . 0)
                \times 4/7 {
                    f'2 ~
                    f'8
                }
            }

        This is default behavior.

    ..  container:: example

        **Example 13.** Set `is_diminution` to false to produce
        agumented tuplets:

        ::

            >>> pitches = "f'"
            >>> durations = [Duration(5, 14)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     is_diminution=False
            ...     )
            >>> staff = Staff(leaves)
            >>> time_signature = TimeSignature((5, 14))
            >>> attach(time_signature, staff)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                \time 5/14
                \tweak #'text #tuplet-number::calc-fraction-text
                \tweak #'edge-height #'(0.7 . 0)
                \times 8/7 {
                    f'4 ~
                    f'16
                }
            }

    ..  container:: example

        **Example 14.** None-valued elements in `pitches` result in
        multimeasure rests when the multimeasure rest keyword is set:

        ::

            >>> pitches = [None]
            >>> durations = [Duration(3, 8), Duration(5, 8)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_multimeasure_rests=True,
            ...     )
            >>> leaves
            Selection(MultimeasureRest('R1 * 3/8'), MultimeasureRest('R1 * 5/8'))

        ::

            >>> staff = Staff([
            ...     Measure((3, 8), [leaves[0]]),
            ...     Measure((5, 8), [leaves[1]]),
            ...     ])
            >>> staff.context_name = 'RhythmicStaff'
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new RhythmicStaff {
                {
                    \time 3/8
                    R1 * 3/8
                }
                {
                    \time 5/8
                    R1 * 5/8
                }
            }

    ..  container:: example

        **Example 15.** Uses Messiaen-style ties:

        ::

            >>> pitches = [0]
            >>> durations = [Duration(13, 16)]
            >>> leaves = scoretools.make_leaves(
            ...     pitches,
            ...     durations,
            ...     use_messiaen_style_ties=True,
            ...     )
            >>> staff = Staff(leaves)
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                c'2.
                c'16 \repeatTie
            }

    Returns selection of leaves.
    '''
    from abjad.tools import scoretools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions,
        size,
    )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    duration_groups = \
        Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    result = []
    for duration_group in duration_groups:
        # get factors in denominator of duration group other than 1, 2.
        factors = set(mathtools.factors(duration_group[0].denominator))
        factors.discard(1)
        factors.discard(2)
        current_pitches = pitches[0:len(duration_group)]
        pitches = pitches[len(duration_group):]
        if len(factors) == 0:
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=
                    decrease_durations_monotonically,
                    forbidden_written_duration=forbidden_written_duration,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                )
                result.extend(leaves)
        else:
            # compute tuplet prolation
            denominator = duration_group[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / durationtools.Duration(*multiplier)
            duration_group = [
                ratio * durationtools.Duration(duration)
                for duration in duration_group
            ]
            # make tuplet leaves
            tuplet_leaves = []
            for pitch, duration in zip(current_pitches, duration_group):
                leaves = _make_leaf_on_pitch(
                    pitch,
                    duration,
                    decrease_durations_monotonically=\
                        decrease_durations_monotonically,
                    use_multimeasure_rests=use_multimeasure_rests,
                    use_messiaen_style_ties=use_messiaen_style_ties,
                    )
                tuplet_leaves.extend(leaves)
            tuplet = scoretools.Tuplet(multiplier, tuplet_leaves)
            if is_diminution and not tuplet.is_diminution:
                tuplet.toggle_prolation()
            elif not is_diminution and tuplet.is_diminution:
                tuplet.toggle_prolation()
            result.append(tuplet)

    result = selectiontools.Selection(result)
    return result
예제 #12
0
def make_notes(pitches, durations, decrease_durations_monotonically=True):
    r'''Make notes according to `pitches` and `durations`.

    Cycle through `pitches` when the length of `pitches` is less than the
    length of `durations`:

    ::

        >>> scoretools.make_notes([0], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("c'8"), Note("c'8"))

    Cycle through `durations` when the length of `durations` is less than the
    length of `pitches`:

    ::

        >>> scoretools.make_notes([0, 2, 4, 5, 7], [(1, 16), (1, 8), (1, 8)])
        Selection(Note("c'16"), Note("d'8"), Note("e'8"), Note("f'16"), Note("g'8"))

    Create ad hoc tuplets for nonassignable durations:

    ::

        >>> scoretools.make_notes([0], [(1, 16), (1, 12), (1, 8)])
        Selection(Note("c'16"), Tuplet(Multiplier(2, 3), "c'8"), Note("c'8"))

    Set ``decrease_durations_monotonically=True`` to express tied values
    in decreasing duration:

    ::

        >>> scoretools.make_notes(
        ...     [0],
        ...     [(13, 16)],
        ...     decrease_durations_monotonically=True,
        ...     )
        Selection(Note("c'2."), Note("c'16"))

    Set ``decrease_durations_monotonically=False`` to express tied
    values in increasing duration:

    ::

        >>> scoretools.make_notes(
        ...     [0],
        ...     [(13, 16)],
        ...     decrease_durations_monotonically=False,
        ...     )
        Selection(Note("c'16"), Note("c'2."))

    Set `pitches` to a single pitch or a sequence of pitches.

    Set `durations` to a single duration or a list of durations.

    Returns selection.
    '''
    from abjad.tools import scoretools
    from abjad.tools import selectiontools

    if isinstance(pitches, str):
        pitches = pitches.split()

    if not isinstance(pitches, list):
        pitches = [pitches]

    if isinstance(durations, (numbers.Number, tuple)):
        durations = [durations]

    nonreduced_fractions = [mathtools.NonreducedFraction(_) for _ in durations]
    size = max(len(nonreduced_fractions), len(pitches))
    nonreduced_fractions = sequencetools.repeat_sequence_to_length(
        nonreduced_fractions,
        size,
    )
    pitches = sequencetools.repeat_sequence_to_length(pitches, size)
    Duration = durationtools.Duration
    durations = Duration._group_nonreduced_fractions_by_implied_prolation(
        nonreduced_fractions)

    def _make_unprolated_notes(
        pitches,
        durations,
        decrease_durations_monotonically=decrease_durations_monotonically,
    ):
        assert len(pitches) == len(durations)
        result = []
        for pitch, duration in zip(pitches, durations):
            result.extend(
                scoretools.make_tied_leaf(
                    scoretools.Note,
                    duration,
                    pitches=pitch,
                    decrease_durations_monotonically=
                    decrease_durations_monotonically,
                ))
        return result

    result = []
    for duration in durations:
        # get factors in denominator of duration group duration other than 1, 2.
        factors = set(mathtools.factors(duration[0].denominator))
        factors.discard(1)
        factors.discard(2)
        ps = pitches[0:len(duration)]
        pitches = pitches[len(duration):]
        if len(factors) == 0:
            result.extend(
                _make_unprolated_notes(ps,
                                       duration,
                                       decrease_durations_monotonically=
                                       decrease_durations_monotonically))
        else:
            # compute prolation
            denominator = duration[0].denominator
            numerator = mathtools.greatest_power_of_two_less_equal(denominator)
            multiplier = (numerator, denominator)
            ratio = 1 / fractions.Fraction(*multiplier)
            duration = [ratio * durationtools.Duration(d) for d in duration]
            ns = _make_unprolated_notes(ps,
                                        duration,
                                        decrease_durations_monotonically=
                                        decrease_durations_monotonically)
            t = scoretools.Tuplet(multiplier, ns)
            result.append(t)

    # return result
    result = selectiontools.Selection(result)
    return result