def _add_or_remove_notes_to_achieve_written_duration(self, new_written_duration): from abjad.tools import scoretools from abjad.tools import notetools from abjad.tools import spannertools from abjad.tools import tuplettools from abjad.tools.scoretools import attach 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.TieSpanner): spanner.detach() elif new_written_duration.has_power_of_two_denominator: durations = notetools.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.TieSpanner): spanner.detach() 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.TieSpanner) if not ties: tie = spannertools.TieSpanner() attach(tie, list(self)) self[-1]._splice(extra_leaves, grow_spanners=True) else: durations = notetools.make_notes(0, new_written_duration) assert isinstance(durations[0], tuplettools.Tuplet) fmtuplet = durations[0] new_chain_written = fmtuplet[0]._get_tie_chain()._preprolated_duration self._add_or_remove_notes_to_achieve_written_duration(new_chain_written) multiplier = fmtuplet.multiplier tuplettools.Tuplet(multiplier, self.leaves) return self[0]._get_tie_chain()
def fill_measures_in_expr_with_minimal_number_of_notes(expr, decrease_durations_monotonically=True, iterctrl=None): '''Fill measures in `expr` with minimal number of notes that decrease durations monotonically: :: >>> measure = Measure((5, 18), []) :: >>> measuretools.fill_measures_in_expr_with_minimal_number_of_notes( ... measure, decrease_durations_monotonically=True) .. doctest:: >>> f(measure) { \time 5/18 \scaleDurations #'(8 . 9) { c'4 ~ c'16 } } Fill measures in `expr` with minimal number of notes that increase durations monotonically: :: >>> measure = Measure((5, 18), []) :: >>> measuretools.fill_measures_in_expr_with_minimal_number_of_notes( ... measure, decrease_durations_monotonically=False) .. doctest:: >>> f(measure) { \time 5/18 \scaleDurations #'(8 . 9) { c'16 ~ c'4 } } Returns none. ''' from abjad.tools import contexttools from abjad.tools import iterationtools if iterctrl is None: iterctrl = lambda measure, i: True for i, measure in enumerate(iterationtools.iterate_measures_in_expr(expr)): if iterctrl(measure, i): time_signature = measure.time_signature written_duration = time_signature.duration / time_signature.implied_prolation notes = notetools.make_notes(0, written_duration, decrease_durations_monotonically=decrease_durations_monotonically) measure[:] = notes
def _make_container(self, division): numerator, denominator = division # eventually allow for non-power-of-two divisions assert mathtools.is_positive_integer_power_of_two(denominator) denominator_multiplier = 2 ** self.denominator_multiplier_exponent denominator *= denominator_multiplier unit_duration = durationtools.Duration(1, denominator) numerator *= denominator_multiplier notes = notetools.make_notes(numerator * [0], [unit_duration]) container = containertools.Container(notes) if self.beam_each_cell: beam = spannertools.BeamSpanner() attach(beam, container) return container
def _set_duration(self, new_duration): from abjad.tools import leaftools from abjad.tools import notetools from abjad.tools import spannertools from abjad.tools import tuplettools from abjad.tools.scoretools import attach new_duration = durationtools.Duration(new_duration) # change LilyPond multiplier if leaf already has LilyPond multiplier if self.lilypond_duration_multiplier is not None: multiplier = new_duration / self.written_duration self.lilypond_duration_multiplier = multiplier 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 = notetools.make_notes(0, new_duration) if isinstance(components[0], leaftools.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.TieSpanner): tie = spannertools.TieSpanner() attach(tie, all_leaves) return all_leaves else: assert isinstance(components[0], tuplettools.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.TieSpanner): tie = spannertools.TieSpanner() attach(tie, all_leaves) tuplet_multiplier = tuplet.multiplier tuplettools.Tuplet(tuplet_multiplier, all_leaves) return [tuplet]
def __call__(self, pulse_duration): r'''Generate Abjad score components: :: >>> leaf = rhythmtreetools.RhythmTreeLeaf(5) >>> leaf((1, 4)) Selection(Note("c'1"), Note("c'4")) Returns sequence of components. ''' pulse_duration = durationtools.Duration(pulse_duration) total_duration = pulse_duration * self.preprolated_duration if self.is_pitched: return notetools.make_notes(0, total_duration) return resttools.make_rests(total_duration)
def make_repeated_notes(count, duration=durationtools.Duration(1, 8)): r'''Make `count` repeated notes with note head-assignable `duration`: :: >>> notetools.make_repeated_notes(4) Selection(Note("c'8"), Note("c'8"), Note("c'8"), Note("c'8")) Make `count` repeated tie chains with tied `duration`: :: >>> notes = notetools.make_repeated_notes(2, (5, 16)) >>> voice = Voice(notes) .. doctest:: >>> f(voice) \new Voice { c'4 ~ c'16 c'4 ~ c'16 } Make ad hoc tuplet holding `count` repeated notes with non-power-of-two `duration`: :: >>> notetools.make_repeated_notes(3, (1, 12)) Selection(Tuplet(2/3, [c'8, c'8, c'8]),) Set pitch of all notes created to middle C. Returns list of zero or more newly constructed notes or list of one newly constructed tuplet. ''' from abjad.tools import notetools return notetools.make_notes([0] * count, [duration])
def _to_tuplet_with_ratio(self, proportions, is_diminution=True): from abjad.tools import notetools from abjad.tools import tuplettools # check input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self.written_duration # find basic prolated duration of note in tuplet basic_prolated_duration = target_duration / sum(proportions) # find basic written duration of note in tuplet basic_written_duration = \ basic_prolated_duration.equal_or_greater_assignable # find written duration of each note in tuplet written_durations = [x * basic_written_duration for x in proportions] # make tuplet notes try: notes = [notetools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [durationtools.Duration(x, denominator) for x in proportions] notes = notetools.make_notes(0, note_durations) # make tuplet tuplet = tuplettools.FixedDurationTuplet(target_duration, notes) # fix tuplet contents if necessary tuplet._fix() # change prolation if necessary if not tuplet.multiplier == 1: if is_diminution: if not tuplet.is_diminution: tuplet.toggle_prolation() else: if tuplet.is_diminution: tuplet.toggle_prolation() # return tuplet return tuplet
def make_notes(self, n=None, written_duration=None): r'''Make first `n` notes in pitch class segment. Set `n` equal to `n` or length of segment. Set `written_duration` equal to `written_duration` or ``1/8``: :: >>> notes = named_pitch_segment.make_notes() >>> staff = Staff(notes) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { bf,8 aqs8 fs'8 g'8 bqf8 g'8 } Allow nonassignable `written_duration`: :: >>> notes = named_pitch_segment.make_notes(4, Duration(5, 16)) >>> staff = Staff(notes) >>> time_signature = contexttools.TimeSignatureMark((5, 4)) >>> attach(time_signature, staff) TimeSignatureMark((5, 4))(Staff{8}) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 bf,4 ~ bf,16 aqs4 ~ aqs16 fs'4 ~ fs'16 g'4 ~ g'16 } Returns list of notes. ''' from abjad.tools import durationtools from abjad.tools import iterationtools from abjad.tools import notetools from abjad.tools import pitchtools n = n or len(self) written_duration = written_duration or durationtools.Duration(1, 8) result = notetools.make_notes([0] * n, [written_duration]) for i, tie_chain in enumerate( iterationtools.iterate_tie_chains_in_expr(result)): pitch = self[i % len(self)] for note in tie_chain: note.written_pitch = pitch return result
def to_tuplet(self, proportions, dotted=False, is_diminution=True): r"""Change tie chain to tuplet. .. container:: example **Example 1.** Change tie chain to diminished tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.HairpinSpanner(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> staff.override.dynamic_line_spanner.staff_padding = 3 >>> time_signature = contexttools.TimeSignatureMark((7, 16)) >>> attach(time_signature, staff) TimeSignatureMark((7, 16))(Staff{3}) .. doctest:: >>> f(staff) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 \< \p ~ c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> tie_chain = inspect(staff[0]).get_tie_chain() >>> tie_chain.to_tuplet([2, 1, 1, 1], is_diminution=True) FixedDurationTuplet(3/16, [c'8, c'16, c'16, c'16]) .. doctest:: >>> f(staff) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 3/5 { c'8 \< \p c'16 c'16 c'16 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP .. container:: example **Example 2.** Change tie chain to augmented tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.HairpinSpanner(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> staff.override.dynamic_line_spanner.staff_padding = 3 >>> time_signature = contexttools.TimeSignatureMark((7, 16)) >>> attach(time_signature, staff) TimeSignatureMark((7, 16))(Staff{3}) .. doctest:: >>> f(staff) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 \< \p ~ c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> tie_chain = inspect(staff[0]).get_tie_chain() >>> tie_chain.to_tuplet([2, 1, 1, 1], is_diminution=False) FixedDurationTuplet(3/16, [c'16, c'32, c'32, c'32]) .. doctest:: >>> f(staff) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 6/5 { c'16 \< \p c'32 c'32 c'32 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP Returns tuplet. """ from abjad.tools import scoretools from abjad.tools import mathtools from abjad.tools import mutationtools from abjad.tools import notetools from abjad.tools import spannertools from abjad.tools import tuplettools # coerce input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self._preprolated_duration # find prolated duration of each note in tuplet prolated_duration = target_duration / sum(proportions) # find written duration of each notes in tuplet if is_diminution: if dotted: basic_written_duration = prolated_duration.equal_or_greater_assignable else: basic_written_duration = prolated_duration.equal_or_greater_power_of_two else: if dotted: basic_written_duration = prolated_duration.equal_or_lesser_assignable else: basic_written_duration = prolated_duration.equal_or_lesser_power_of_two # find written duration of each note in tuplet written_durations = [x * basic_written_duration for x in proportions] # make tuplet notes try: notes = [notetools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [durationtools.Duration(x, denominator) for x in proportions] notes = notetools.make_notes(0, note_durations) # make tuplet tuplet = tuplettools.FixedDurationTuplet(target_duration, notes) # replace tie chain with tuplet mutationtools.mutate(self).replace(tuplet) # untie tuplet for spanner in tuplet._get_spanners(spannertools.TieSpanner): spanner.detach() # return tuplet return tuplet
def make_gridded_test_rhythm(grid_length, rhythm_number, denominator=16): r'''Make test rhythm number `rhythm_number` that fits `grid_length`. Returns selection of one or more possibly tied notes. .. container:: example **Example 1.** The eight test rhythms that fit a length-``4`` grid: :: >>> for rhythm_number in range(8): ... notes = timesignaturetools.make_gridded_test_rhythm( ... 4, rhythm_number, denominator=4) ... measure = Measure((4, 4), notes) ... print '{}\t{}'.format(rhythm_number, measure) ... 0 |4/4 c'1| 1 |4/4 c'2. c'4| 2 |4/4 c'2 c'4 c'4| 3 |4/4 c'2 c'2| 4 |4/4 c'4 c'4 c'2| 5 |4/4 c'4 c'4 c'4 c'4| 6 |4/4 c'4 c'2 c'4| 7 |4/4 c'4 c'2.| .. container:: example **Example 2.** The sixteenth test rhythms for that a length-``5`` grid: :: >>> for rhythm_number in range(16): ... notes = timesignaturetools.make_gridded_test_rhythm( ... 5, rhythm_number, denominator=4) ... measure = Measure((5, 4), notes) ... print '{}\t{}'.format(rhythm_number, measure) ... 0 |5/4 c'1 ~ c'4| 1 |5/4 c'1 c'4| 2 |5/4 c'2. c'4 c'4| 3 |5/4 c'2. c'2| 4 |5/4 c'2 c'4 c'2| 5 |5/4 c'2 c'4 c'4 c'4| 6 |5/4 c'2 c'2 c'4| 7 |5/4 c'2 c'2.| 8 |5/4 c'4 c'4 c'2.| 9 |5/4 c'4 c'4 c'2 c'4| 10 |5/4 c'4 c'4 c'4 c'4 c'4| 11 |5/4 c'4 c'4 c'4 c'2| 12 |5/4 c'4 c'2 c'2| 13 |5/4 c'4 c'2 c'4 c'4| 14 |5/4 c'4 c'2. c'4| 15 |5/4 c'4 c'1| Use for testing metrical hierarchy establishment. ''' from abjad.tools import notetools # check input assert mathtools.is_positive_integer(grid_length) assert isinstance(rhythm_number, int) assert mathtools.is_positive_integer_power_of_two(denominator) # find count of all rhythms that fit grid length rhythm_count = 2 ** (grid_length - 1) # read rhythm number cyclically to allow large and negative rhythm numbers rhythm_number = rhythm_number % rhythm_count # find binary representation of rhythm binary_representation = mathtools.integer_to_binary_string(rhythm_number) binary_representation = binary_representation.zfill(grid_length) # partition binary representation of rhythm parts = sequencetools.partition_sequence_by_value_of_elements(binary_representation) # find durations durations = [durationtools.Duration(len(part), denominator) for part in parts] # make notes notes = notetools.make_notes([0], durations) # return notes return notes
def make_repeated_notes_with_shorter_notes_at_end( pitch, written_duration, total_duration, prolation=1): r'''Make repeated notes with `pitch` and `written_duration` summing to `total_duration` under `prolation`: :: >>> args = [0, Duration(1, 16), Duration(1, 4)] >>> notes = notetools.make_repeated_notes_with_shorter_notes_at_end(*args) >>> voice = Voice(notes) .. doctest:: >>> f(voice) \new Voice { c'16 c'16 c'16 c'16 } Fill power-of-two remaining duration with power-of-two notes of lesser written duration: :: >>> args = [0, Duration(1, 16), Duration(9, 32)] >>> notes = notetools.make_repeated_notes_with_shorter_notes_at_end(*args) >>> voice = Voice(notes) .. doctest:: >>> f(voice) \new Voice { c'16 c'16 c'16 c'16 c'32 } Fill non-power-of-two remaining duration with ad hoc tuplet: :: >>> args = [0, Duration(1, 16), Duration(4, 10)] >>> notes = notetools.make_repeated_notes_with_shorter_notes_at_end(*args) >>> voice = Voice(notes) .. doctest:: >>> f(voice) \new Voice { c'16 c'16 c'16 c'16 c'16 c'16 \times 4/5 { c'32 } } Set `prolation` when making notes in a measure with a non-power-of-two denominator. Returns list of components. ''' from abjad.tools import notetools written_duration = durationtools.Duration(written_duration) total_duration = durationtools.Duration(total_duration) prolation = durationtools.Duration(prolation) prolation = fractions.Fraction(prolation) duration = prolation * written_duration current_duration = durationtools.Duration(0) result = [] while current_duration + duration <= total_duration: result.append(notetools.Note(pitch, written_duration)) current_duration += duration remainder_duration = total_duration - current_duration if durationtools.Duration(0) < remainder_duration: multiplied_remainder = remainder_duration / prolation result.extend(notetools.make_notes(pitch, [multiplied_remainder])) result = selectiontools.Selection(result) return result
def __call__(self, pulse_duration): pulse_duration = durationtools.Duration(pulse_duration) total_duration = pulse_duration * self.preprolated_duration return notetools.make_notes(0, total_duration)
def make_notes(self, n=None, written_duration=None): r'''Make first `n` notes in pitch class segment. Set `n` equal to `n` or length of segment. Set `written_duration` equal to `written_duration` or ``1/8``: :: >>> pitch_class_segment = pitchtools.PitchClassSegment( ... [2, 4.5, 6, 11, 4.5, 10]) :: >>> notes = pitch_class_segment.make_notes() >>> staff = Staff(notes) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { d'8 eqs'8 fs'8 b'8 eqs'8 bf'8 } Allow nonassignable `written_duration`: :: >>> notes = pitch_class_segment.make_notes(4, Duration(5, 16)) >>> staff = Staff(notes) >>> time_signature = contexttools.TimeSignatureMark((5, 4)) >>> attach(time_signature, staff) TimeSignatureMark((5, 4))(Staff{8}) >>> show(staff) # doctest: +SKIP .. doctest:: >>> f(staff) \new Staff { \time 5/4 d'4 ~ d'16 eqs'4 ~ eqs'16 fs'4 ~ fs'16 b'4 ~ b'16 } Returns list of notes. ''' from abjad.tools import iterationtools from abjad.tools import notetools from abjad.tools import pitchtools n = n or len(self) written_duration = written_duration or durationtools.Duration(1, 8) result = notetools.make_notes([0] * n, [written_duration]) for i, tie_chain in enumerate( iterationtools.iterate_tie_chains_in_expr(result)): pitch_class = pitchtools.NamedPitchClass(self[i % len(self)]) pitch = pitchtools.NamedPitch(pitch_class, 4) for note in tie_chain: note.written_pitch = pitch return result