def with_power_of_two_denominator(self, contents_multiplier=1 ) -> "TimeSignature": """ Makes new time signature equivalent to current time signature with power-of-two denominator. .. container:: example Non-power-of-two denominator with power-of-two denominator: >>> time_signature = abjad.TimeSignature((3, 12)) >>> time_signature.with_power_of_two_denominator() TimeSignature((2, 8)) """ contents_multiplier = Multiplier(contents_multiplier) contents_multiplier = Multiplier(contents_multiplier) non_power_of_two_denominator = self.denominator if contents_multiplier == Multiplier(1): power_of_two_denominator = mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator) else: power_of_two_denominator = mathtools.greatest_power_of_two_less_equal( non_power_of_two_denominator, 1) non_power_of_two_pair = NonreducedFraction(self.pair) power_of_two_fraction = non_power_of_two_pair.with_denominator( power_of_two_denominator) power_of_two_pair = power_of_two_fraction.pair return type(self)(power_of_two_pair)
def prolation(self) -> Multiplier: """ Gets prolation. """ prolations = [Multiplier(1)] + self._prolations() products = mathtools.cumulative_products(prolations) return products[-1]
def prolation(self) -> Multiplier: r""" Gets prolation. .. container:: example REGRESSION. Works with grace notes (and containers): >>> voice = abjad.Voice( ... r"\times 2/3 { c'4 d' e' } \times 2/3 { f' g' a' }" ... ) >>> container_1 = abjad.GraceContainer("cs'16") >>> abjad.attach(container_1, voice[0][1]) >>> container_2 = abjad.AfterGraceContainer("fs'16") >>> abjad.attach(container_2, voice[1][2]) >>> abjad.show(voice) # doctest: +SKIP .. docs:: >>> abjad.f(voice) \new Voice { \times 2/3 { c'4 \grace { cs'16 } d'4 e'4 } \times 2/3 { f'4 g'4 \afterGrace a'4 { fs'16 } } } >>> abjad.inspect(voice).parentage().prolation Multiplier(1, 1) >>> abjad.inspect(container_1).parentage().prolation Multiplier(2, 3) >>> abjad.inspect(container_1[0]).parentage().prolation Multiplier(2, 3) >>> abjad.inspect(container_2).parentage().prolation Multiplier(2, 3) >>> abjad.inspect(container_2[0]).parentage().prolation Multiplier(2, 3) """ prolations = [Multiplier(1)] + self._prolations() products = mathtools.cumulative_products(prolations) return products[-1]
def _prolations(self): prolations = [] default = Multiplier(1) for parent in self: prolation = getattr(parent, "implied_prolation", default) prolations.append(prolation) return prolations
def __init__( self, contact_point: typings.IntegerPair = None, ) -> None: contact_point_ = None if contact_point is not None: contact_point_ = Multiplier(contact_point) assert 0 <= contact_point_ <= 1 self._contact_point = contact_point_
def __init__( self, contact_point: typing.Tuple[int, int] = None ) -> None: contact_point_ = None if contact_point is not None: contact_point_ = Multiplier(contact_point) assert 0 <= contact_point_ <= 1 self._contact_point = contact_point_
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 duration_to_milliseconds(self, duration) -> Duration: """ Gets millisecond value of ``duration`` under a given metronome mark. .. container:: example Dotted sixteenth lasts 1500 msec at quarter equals 60: >>> mark = abjad.MetronomeMark((1, 4), 60) >>> mark.duration_to_milliseconds((3, 8)) Duration(1500, 1) """ assert isinstance(self.reference_duration, Duration) denominator = self.reference_duration.denominator numerator = self.reference_duration.numerator whole_note_duration = 1000 whole_note_duration *= Multiplier(denominator, numerator) whole_note_duration *= Multiplier(60, self.units_per_minute) duration = Duration(duration) return Duration(duration * whole_note_duration)
def slope(self): """ Gets slope of interval segment. .. container:: example The slope of a interval segment is the sum of its intervals divided by its length: >>> abjad.IntervalSegment([1, 2]).slope Multiplier(3, 2) Returns multiplier. """ result = sum([x.number for x in self]) / len(self) return Multiplier.from_float(result)
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 markup(self) -> Markup: r""" Gets markup of bow contact point. .. container:: example One quarter of the way from frog to point: >>> indicator = abjad.BowContactPoint((1, 4)) >>> print(format(indicator.markup, 'lilypond')) \markup { \center-align \vcenter \fraction 1 4 } >>> abjad.show(indicator.markup) # doctest: +SKIP .. container:: example Three fifths of the way from frog to point: >>> indicator = abjad.BowContactPoint((3, 5)) >>> print(format(indicator.markup, 'lilypond')) \markup { \center-align \vcenter \fraction 3 5 } >>> abjad.show(indicator.markup) # doctest: +SKIP """ if self.contact_point is None: contact_point = Multiplier(0, 1) else: contact_point = self.contact_point markup = Markup.fraction( contact_point.numerator, contact_point.denominator, ) markup = markup.vcenter() markup = markup.center_align() return markup
def implied_prolation(self) -> Multiplier: r""" Gets implied prolation of tremolo container. .. container:: example Defined equal to count. >>> tremolo_container = abjad.TremoloContainer(2, "<c' d'>16 e'16") >>> abjad.show(tremolo_container) # doctest: +SKIP >>> tremolo_container.implied_prolation Multiplier(2, 1) """ multiplier = Multiplier(self.count) return multiplier
def __div__(self, argument) -> "MetronomeMark": """ Divides metronome mark by ``argument``. .. container:: example Divides metronome mark by number: >>> abjad.MetronomeMark((1, 4), 60) / 2 MetronomeMark(reference_duration=Duration(1, 4), units_per_minute=30) .. container:: example Divides metronome mark by other metronome mark: >>> abjad.MetronomeMark((1, 4), 60) / abjad.MetronomeMark((1, 4), 40) Multiplier(3, 2) """ if self.is_imprecise: raise exceptions.ImpreciseMetronomeMarkError if getattr(argument, "is_imprecise", False): raise exceptions.ImpreciseMetronomeMarkError assert isinstance(self.quarters_per_minute, Fraction) if isinstance(argument, type(self)): assert isinstance(argument.quarters_per_minute, Fraction) result = self.quarters_per_minute / argument.quarters_per_minute return Multiplier(result) elif isinstance(argument, (int, Fraction)): assert isinstance(self.units_per_minute, (int, Fraction)) units_per_minute = self.units_per_minute / argument if mathtools.is_integer_equivalent_number(units_per_minute): units_per_minute = int(units_per_minute) else: units_per_minute = Fraction(units_per_minute) result = new(self, units_per_minute=units_per_minute) return result else: raise TypeError(f"must be number or metronome mark: {argument!r}.")
def multiplier(self, argument): if isinstance(argument, (NonreducedFraction, type(None))): multiplier = argument else: multiplier = Multiplier(argument) self._multiplier = multiplier
def list_related_tempos( self, maximum_numerator=None, maximum_denominator=None, integer_tempos_only=False, ) -> typing.List[typing.Tuple["MetronomeMark", "Ratio"]]: r""" Lists related tempos. .. container:: example Rewrites tempo ``4=58`` by ratios ``n:d`` such that ``1 <= n <= 8`` and ``1 <= d <= 8``. >>> mark = abjad.MetronomeMark((1, 4), 58) >>> pairs = mark.list_related_tempos( ... maximum_numerator=8, ... maximum_denominator=8, ... ) >>> for tempo, ratio in pairs: ... string = f'{tempo!s}\t{ratio!s}' ... print(string) 4=29 1:2 4=33+1/7 4:7 4=34+4/5 3:5 4=36+1/4 5:8 4=38+2/3 2:3 4=41+3/7 5:7 4=43+1/2 3:4 4=46+2/5 4:5 4=48+1/3 5:6 4=49+5/7 6:7 4=50+3/4 7:8 4=58 1:1 4=66+2/7 8:7 4=67+2/3 7:6 4=69+3/5 6:5 4=72+1/2 5:4 4=77+1/3 4:3 4=81+1/5 7:5 4=87 3:2 4=92+4/5 8:5 4=96+2/3 5:3 4=101+1/2 7:4 4=116 2:1 .. container:: example Integer-valued tempos only: >>> mark = abjad.MetronomeMark((1, 4), 58) >>> pairs = mark.list_related_tempos( ... maximum_numerator=16, ... maximum_denominator=16, ... integer_tempos_only=True, ... ) >>> for tempo, ratio in pairs: ... string = f'{tempo!s}\t{ratio!s}' ... print(string) 4=29 1:2 4=58 1:1 4=87 3:2 4=116 2:1 Constrains ratios such that ``1:2 <= n:d <= 2:1``. """ allowable_numerators = range(1, maximum_numerator + 1) allowable_denominators = range(1, maximum_denominator + 1) numbers = [allowable_numerators, allowable_denominators] enumerator = Enumerator(numbers) pairs = enumerator.yield_outer_product() multipliers = [Multiplier(_) for _ in pairs] multipliers = [_ for _ in multipliers if Fraction(1, 2) <= _ <= Fraction(2)] multipliers.sort() multipliers = sequence(multipliers).remove_repeats() pairs = [] for multiplier in multipliers: new_units_per_minute = multiplier * self.units_per_minute if integer_tempos_only and not mathtools.is_integer_equivalent_number( new_units_per_minute ): continue metronome_mark = type(self)( reference_duration=self.reference_duration, units_per_minute=new_units_per_minute, ) ratio = Ratio(multiplier.pair) pair = (metronome_mark, ratio) pairs.append(pair) return pairs