def __call__(self, pitches, durations) -> Selection: """ Calls note-maker on ``pitches`` and ``durations``. """ from .Tuplet import Tuplet if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, collections.abc.Iterable): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = Sequence( [NonreducedFraction(_) for _ in durations] ) size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = nonreduced_fractions.repeat_to_length(size) pitches = Sequence(pitches).repeat_to_length(size) durations = Duration._group_by_implied_prolation(nonreduced_fractions) result: typing.List[typing.Union[Note, Tuplet]] = [] 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( self._make_unprolated_notes( ps, duration, increase_monotonic=self.increase_monotonic, tag=self.tag, ) ) else: # compute prolation denominator = duration[0].denominator numerator = mathtools.greatest_power_of_two_less_equal( denominator ) multiplier = Multiplier(numerator, denominator) ratio = multiplier.reciprocal duration = [ratio * Duration(d) for d in duration] ns = self._make_unprolated_notes( ps, duration, increase_monotonic=self.increase_monotonic, tag=self.tag, ) tuplet = Tuplet(multiplier, ns) result.append(tuplet) return Selection(result)
def _get_measure_start_offsets(self, component): wrappers = [] prototype = TimeSignature root = inspect(component).parentage().root for component_ in self._iterate_entire_score(root): wrappers_ = inspect(component_).wrappers(prototype) wrappers.extend(wrappers_) pairs = [] for wrapper in wrappers: component = wrapper.component start_offset = inspect(component).timespan().start_offset time_signature = wrapper.indicator pair = start_offset, time_signature pairs.append(pair) offset_zero = Offset(0) default_time_signature = TimeSignature((4, 4)) default_pair = (offset_zero, default_time_signature) if pairs and not pairs[0] == offset_zero: pairs.insert(0, default_pair) elif not pairs: pairs = [default_pair] pairs.sort(key=lambda x: x[0]) score_stop_offset = inspect(root).timespan().stop_offset dummy_last_pair = (score_stop_offset, None) pairs.append(dummy_last_pair) measure_start_offsets = [] for current_pair, next_pair in Sequence(pairs).nwise(): current_start_offset, current_time_signature = current_pair next_start_offset, next_time_signature = next_pair measure_start_offset = current_start_offset while measure_start_offset < next_start_offset: measure_start_offsets.append(measure_start_offset) measure_start_offset += current_time_signature.duration return measure_start_offsets
def _to_measure_number(self, component, measure_number_start_offsets): inspector = inspect(component) component_start_offset = inspector.timespan().start_offset measure_number_start_offsets = measure_number_start_offsets[:] measure_number_start_offsets.append(mathtools.Infinity()) pairs = Sequence(measure_number_start_offsets) pairs = pairs.nwise() for measure_index, pair in enumerate(pairs): if pair[0] <= component_start_offset < pair[-1]: measure_number = measure_index + 1 return measure_number message = "can not find measure number: {!r}, {!r}." message = message.format(component, measure_number_start_offsets) raise ValueError(message)
def check_duplicate_ids(self, argument=None) -> typing.Tuple[typing.List, int]: """ Checks duplicate IDs. """ violators = [] components = iterate(argument).components() total_ids = [id(_) for _ in components] unique_ids = Sequence(total_ids).remove_repeats() if len(unique_ids) < len(total_ids): for current_id in unique_ids: if 1 < total_ids.count(current_id): violators.extend( [_ for _ in components if id(_) == current_id]) return violators, len(total_ids)
def _make_metronome_mark_map(self, score_root): from abjad.utilities.Multiplier import Multiplier from abjad.utilities.Offset import Offset from abjad.utilities.Sequence import Sequence from abjad.indicators.MetronomeMark import MetronomeMark from abjad.timespans.AnnotatedTimespan import AnnotatedTimespan from abjad.timespans.TimespanList import TimespanList pairs = [] all_stop_offsets = set() for component in self._iterate_entire_score(score_root): indicators = component._get_indicators(MetronomeMark) if len(indicators) == 1: metronome_mark = indicators[0] if not metronome_mark.is_imprecise: pair = (component._start_offset, metronome_mark) pairs.append(pair) if component._stop_offset is not None: all_stop_offsets.add(component._stop_offset) pairs.sort(key=lambda _: _[0]) if not pairs: return if pairs[0][0] != 0: return score_stop_offset = max(all_stop_offsets) timespans = TimespanList() clocktime_rate = MetronomeMark((1, 4), 60) clocktime_start_offset = Offset(0) for left, right in Sequence(pairs).nwise(wrapped=True): metronome_mark = left[-1] start_offset = left[0] stop_offset = right[0] # last timespan if stop_offset == 0: stop_offset = score_stop_offset duration = stop_offset - start_offset multiplier = Multiplier(60, metronome_mark.units_per_minute) clocktime_duration = duration / metronome_mark.reference_duration clocktime_duration *= multiplier timespan = AnnotatedTimespan( start_offset=start_offset, stop_offset=stop_offset, annotation=(clocktime_start_offset, clocktime_duration), ) timespans.append(timespan) clocktime_start_offset += clocktime_duration return timespans
def _to_measure_number(self, component, measure_start_offsets): component_start_offset = inspect(component).timespan().start_offset displacement = component_start_offset.displacement if displacement is not None: component_start_offset = Offset( component_start_offset, displacement=None ) # score-initial grace music only: if displacement < 0 and component_start_offset == 0: measure_number = 0 return measure_number measure_start_offsets = measure_start_offsets[:] measure_start_offsets.append(mathtools.Infinity()) pairs = Sequence(measure_start_offsets) pairs = pairs.nwise() for measure_index, pair in enumerate(pairs): if pair[0] <= component_start_offset < pair[-1]: measure_number = measure_index + 1 return measure_number message = f"can not find measure number for {repr(component)}:\n" message += f" {repr(measure_start_offsets)}" raise ValueError(message)
def _split_by_durations( self, durations, cyclic=False, tie_split_notes=True, repeat_ties=False, ): from .AfterGraceContainer import AfterGraceContainer from .Chord import Chord from .GraceContainer import GraceContainer from .Note import Note from .Selection import Selection from .Tuplet import Tuplet durations = [Duration(_) for _ in durations] durations = Sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = Sequence(durations) durations = durations.truncate(weight=leaf_duration) originally_tied = inspect(self).has_indicator(TieIndicator) originally_repeat_tied = inspect(self).has_indicator(RepeatTie) result_selections = [] grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties, ) result_selections.append(selection) result_components = Sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves(grace_notes=False) assert all(isinstance(_, Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() # for leaf in result_leaves: # detach(Tie, leaf) # strip result leaves of all indicators for leaf in result_leaves: detach(object, leaf) # replace leaf with flattened result if self._parent is not None: mutate(self).replace(result_components) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): detach(indicator, self) direction = getattr(indicator, '_time_orientation', enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], Tuplet): mutate(result_components).fuse() # tie split notes if (tie_split_notes and isinstance(self, (Note, Chord)) and 1 < len(result_leaves)): result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties) #assert not inspect(result_leaves[0]).has_indicator(RepeatTie) detach(RepeatTie, result_leaves[0]) #assert not inspect(result_leaves[-1]).has_indicator(TieIndicator) detach(TieIndicator, result_leaves[-1]) if originally_repeat_tied: tie = RepeatTie() attach(tie, result_leaves[0]) if originally_tied: tie = TieIndicator() attach(tie, result_leaves[-1]) assert isinstance(result_leaves, Selection) assert all(isinstance(_, Leaf) for _ in result_leaves) return result_leaves
def __call__(self, pitches, durations) -> Selection: """ Calls leaf-maker on ``pitches`` and ``durations``. Returns selection. """ from .Tuplet import Tuplet if isinstance(pitches, str): pitches = pitches.split() if not isinstance(pitches, collections.Iterable): pitches = [pitches] if isinstance(durations, (numbers.Number, tuple)): durations = [durations] nonreduced_fractions = Sequence( [NonreducedFraction(_) for _ in durations]) size = max(len(nonreduced_fractions), len(pitches)) nonreduced_fractions = nonreduced_fractions.repeat_to_length(size) pitches = Sequence(pitches).repeat_to_length(size) duration_groups = Duration._group_by_implied_prolation( nonreduced_fractions) result: typing.List[typing.Union[Tuplet, Leaf]] = [] for duration_group in duration_groups: # get factors in denominator of duration group other than 1, 2. factors = mathtools.factors(duration_group[0].denominator) factors = set(factors) 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 = self._make_leaf_on_pitch( pitch, duration, increase_monotonic=self.increase_monotonic, forbidden_note_duration=self.forbidden_note_duration, forbidden_rest_duration=self.forbidden_rest_duration, repeat_ties=self.repeat_ties, skips_instead_of_rests=self.skips_instead_of_rests, tag=self.tag, use_multimeasure_rests=self.use_multimeasure_rests, ) 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 / Duration(*multiplier) duration_group = [ ratio * Duration(duration) for duration in duration_group ] # make tuplet leaves tuplet_leaves: typing.List[Leaf] = [] for pitch, duration in zip(current_pitches, duration_group): leaves = self._make_leaf_on_pitch( pitch, duration, increase_monotonic=self.increase_monotonic, repeat_ties=self.repeat_ties, skips_instead_of_rests=self.skips_instead_of_rests, tag=self.tag, use_multimeasure_rests=self.use_multimeasure_rests, ) tuplet_leaves.extend(leaves) tuplet = Tuplet(multiplier, tuplet_leaves) result.append(tuplet) return Selection(result)
def _split_by_durations(self, durations, cyclic=False): from .Chord import Chord from .Note import Note from .Selection import Selection from .Tuplet import Tuplet durations = [Duration(_) for _ in durations] durations = Sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = Sequence(durations) durations = durations.truncate(weight=leaf_duration) originally_tied = inspect(self).has_indicator(Tie) originally_repeat_tied = inspect(self).has_indicator(RepeatTie) result_selections = [] # detach grace containers before_grace_container = self._before_grace_container if before_grace_container is not None: detach(before_grace_container, self) after_grace_container = self._after_grace_container if after_grace_container is not None: detach(after_grace_container, self) # do other things leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration(preprolated_duration) result_selections.append(selection) result_components = Sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves(grace=False) assert all(isinstance(_, Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() # strip result leaves of all indicators for leaf in result_leaves: detach(object, leaf) # replace leaf with flattened result if inspect(self).parentage().parent is not None: mutate(self).replace(result_components) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): detach(indicator, self) direction = getattr(indicator, "_time_orientation", enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # reattach grace containers if before_grace_container is not None: attach(before_grace_container, first_result_leaf) if after_grace_container is not None: attach(after_grace_container, last_result_leaf) # fuse tuplets if isinstance(result_components[0], Tuplet): mutate(result_components).fuse() # tie split notes if isinstance(self, (Note, Chord)) and 1 < len(result_leaves): result_leaves._attach_tie_to_leaves() if originally_repeat_tied and not inspect( result_leaves[0]).has_indicator(RepeatTie): attach(RepeatTie(), result_leaves[0]) if originally_tied and not inspect( result_leaves[-1]).has_indicator(Tie): attach(Tie(), result_leaves[-1]) assert isinstance(result_leaves, Selection) assert all(isinstance(_, Leaf) for _ in result_leaves) return result_leaves