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])
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])
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
def _fuse_tuplets(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_parent( self, prototype=(scoretools.Tuplet, )) if len(self) == 0: return None first = self[0] first_multiplier = first.multiplier first_type = type(first) for tuplet in self[1:]: if tuplet.multiplier != first_multiplier: message = 'tuplets must carry same multiplier.' raise ValueError(message) if type(tuplet) != first_type: message = 'tuplets must be same type.' raise TypeError(message) if isinstance(first, scoretools.FixedDurationTuplet): total_contents_duration = sum([x._contents_duration for x in self]) new_target_duration = first_multiplier * total_contents_duration new_tuplet = scoretools.FixedDurationTuplet( new_target_duration, []) elif isinstance(first, scoretools.Tuplet): new_tuplet = scoretools.Tuplet(first_multiplier, []) else: message = 'unknown tuplet type.' raise TypeError(message) wrapped = False if self[0]._get_parentage().root is not \ self[-1]._get_parentage().root: dummy_container = scoretools.Container(self) wrapped = True mutate(self).swap(new_tuplet) if wrapped: del (dummy_container[:]) return new_tuplet
def 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
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)
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()
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]
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
def p_tuplet__FRACTION__container(self, p): r'''tuplet : FRACTION container ''' p[0] = scoretools.Tuplet(p[1], p[2][:])
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
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