def calculate_and_octave_reduce_interval(self, interval1, interval2): interval = abjad.NamedInterval().from_pitch_carriers( interval1, interval2 ) if interval.semitones > 12: interval -= abjad.NamedInterval('P8') return interval
def test_init(input_, semitones, name): class_ = abjad.NamedInterval if isinstance(semitones, type) and issubclass(semitones, Exception): with pytest.raises(semitones): class_(input_) return instance = class_(input_) assert float(instance) == semitones assert instance.name == name abjad.NamedInterval(instance) abjad.NumberedInterval(instance) abjad.NamedIntervalClass(instance) abjad.NumberedIntervalClass(instance) if isinstance(input_, str): group_dict = abjad.pitch._lib._interval_name_abbreviation_regex.match( input_).groupdict() inflected_up = class_("{}{}{}{}".format( group_dict["direction"] or "", group_dict["quality"], "+", group_dict["number"], )) inflected_down = class_("{}{}{}{}".format( group_dict["direction"] or "", group_dict["quality"], "~", group_dict["number"], )) if (math.sign(float(instance)) == instance.direction_number) and abs(instance.number) != 1: direction = math.sign(float(instance)) assert float(inflected_up) == (abs(float(instance)) + 0.5) * direction assert float(inflected_down) == (abs(float(instance)) - 0.5) * direction
def transpose(self, n=0): """ Transposes named pitch-class by index named interval `n`. .. container:: example >>> interval = abjad.NamedInterval('-M2') >>> abjad.NamedPitchClass('cs').transpose(interval) NamedPitchClass('b') >>> interval = abjad.NamedInterval('P1') >>> abjad.NamedPitchClass('cs').transpose(interval) NamedPitchClass('cs') >>> interval = abjad.NamedInterval('+M2') >>> abjad.NamedPitchClass('cs').transpose(interval) NamedPitchClass('ds') Returns new named pitch-class. """ import abjad interval = abjad.NamedInterval(n) pitch = abjad.NamedPitch((self.name, 4)) pitch = interval.transpose(pitch) return type(self)(pitch)
def __init__( self, root=None, quality_string='major', extent='triad', inversion='root', ): import abjad from abjad.tools import tonalanalysistools root = root or 'c' root = abjad.NamedPitchClass(root) chord_quality = tonalanalysistools.RootlessChordClass( quality_string=quality_string, extent=extent, inversion=inversion, ) npcs = [] for hdi in chord_quality: mdi = abjad.NamedInterval(hdi) npc = root + mdi npcs.append(npc) bass = npcs[0] PitchClassSet.__init__( self, items=npcs, item_class=abjad.NamedPitchClass, ) self._root = root self._chord_quality = chord_quality self._bass = bass
def transpose(self, expr): r""" Transposes music specifier. .. container:: example >>> music_specifier = tsmakers.MusicSpecifier() >>> transposed_music_specifier = music_specifier.transpose('-M2') >>> print(abjad.storage(transposed_music_specifier)) tsmakers.MusicSpecifier() Returns new music specifier. """ if isinstance(expr, str): try: pitch = abjad.NamedPitch(expr) expr = abjad.NamedPitch("C4") - pitch except Exception: expr = abjad.NamedInterval(expr) pitch_handler = self.pitch_handler if pitch_handler is not None: pitch_handler = pitch_handler.transpose(expr) return abjad.new( self, pitch_handler=pitch_handler, )
def __lt__(self, argument): """ Is true when `argument` is a named interval class with a number greater than that of this named interval. .. container:: example >>> interval_class_1 = abjad.NamedIntervalClass('P1') >>> interval_class_2 = abjad.NamedIntervalClass('P1') >>> interval_class_3 = abjad.NamedIntervalClass('m2') >>> interval_class_1 < interval_class_1 False >>> interval_class_1 < interval_class_2 False >>> interval_class_1 < interval_class_3 True >>> interval_class_2 < interval_class_1 False >>> interval_class_2 < interval_class_2 False >>> interval_class_2 < interval_class_3 True >>> interval_class_3 < interval_class_1 False >>> interval_class_3 < interval_class_2 False >>> interval_class_3 < interval_class_3 False Returns true or false. """ import abjad try: argument = type(self)(argument) except Exception: return False if self.number == argument.number: self_semitones = abjad.NamedInterval(self).semitones argument_semitones = abjad.NamedInterval(argument).semitones return self_semitones < argument_semitones return self.number < argument.number
def __init__( self, interval=None, overrides=None, ): import abjad Spanner.__init__(self, overrides=overrides) if interval is not None: interval = abjad.NamedInterval(interval) self._interval = interval
def test_init(input_, semitones, name): class_ = abjad.NamedIntervalClass if isinstance(semitones, type) and issubclass(semitones, Exception): with pytest.raises(semitones): class_(input_) return instance = class_(input_) assert float(instance) == semitones assert instance.name == name abjad.NamedInterval(instance) abjad.NamedIntervalClass(instance) abjad.NumberedInterval(instance) abjad.NumberedIntervalClass(instance)
def adjacent_interval_inversion(iterable): out = [] for i in range(len(iterable) - 1): leaf1 = iterable[i] leaf2 = iterable[i + 1] pitch1 = leaf1.written_pitch pitch2 = leaf2.written_pitch interval = abjad.NamedInterval.from_pitch_carriers(pitch1, pitch2) inverted_interval = abjad.NamedInterval("P1") - interval new_pitch = inverted_interval.transpose(leaf1.written_pitch) new_leaf = copy.copy(leaf1) new_leaf.written_pitch = new_pitch out.append(new_leaf) return out
def transpose_contrabass(selections): octave = abjad.NamedInterval("+P8") for leaf in abjad.select(selections).leaves(pitched=True): if isinstance(leaf, abjad.Note): old_pitch = leaf.written_pitch new_pitch = octave.transpose(old_pitch) leaf.written_pitch = new_pitch elif isinstance(leaf, abjad.Chord): old_pitches = leaf.written_pitches new_pitches = [ octave.transpose(old_pitch) for old_pitch in old_pitches ] leaf.written_pitches = new_pitches else: continue
def __add__(self, interval): r'''Adds named pitch to `interval`. .. container:: example >>> abjad.NamedPitch("cs''") + abjad.NamedInterval('-M2') NamedPitch("b'") >>> abjad.NamedPitch("cs''") + abjad.NamedInterval('P1') NamedPitch("cs''") >>> abjad.NamedPitch("cs''") + abjad.NamedInterval('+M2') NamedPitch("ds''") Returns new named pitch. ''' import abjad interval = abjad.NamedInterval(interval) return interval.transpose(self)
def _apply_trills(self, selections): container = abjad.Container() container.append(selections) for tie in abjad.iterate(container).logical_ties(pitched=True): if isinstance(tie[0], abjad.Chord): old_chord = tie[0] base_pitch = old_chord.written_pitches[0] trill_pitch = old_chord.written_pitches[-1] interval_ = abjad.NamedInterval().from_pitch_carriers( base_pitch, trill_pitch) new_leaf = abjad.Note(base_pitch, old_chord.written_duration) trill_start = abjad.LilyPondLiteral(r'\pitchedTrill', format_slot='before') trill_literal = abjad.LilyPondLiteral( f'\startTrillSpan {trill_pitch}', format_slot='after') trill_stop = abjad.LilyPondLiteral(r'\stopTrillSpan', format_slot='after') abjad.attach(trill_start, new_leaf) abjad.attach(trill_literal, new_leaf) last_leaf = tie[-1] next_leaf = abjad.inspect(last_leaf).leaf(1) if next_leaf != None: abjad.attach(trill_stop, next_leaf) indicators = abjad.inspect(old_chord).indicators() for indicator in indicators: abjad.attach(indicator, new_leaf) parent = abjad.inspect(old_chord).parentage().parent parent[parent.index(old_chord)] = new_leaf tail = abjad.select(tie).leaves()[1:] for leaf in tail: new_tail = abjad.Note(base_pitch, leaf.written_duration) parent = abjad.inspect(leaf).parentage().parent parent[parent.index(leaf)] = new_tail indicators = abjad.inspect(leaf).indicators() for indicator in indicators: abjad.attach(indicator, new_tail) return container[:]
def __sub__(self, argument): r'''Subtracts `argument` from named pitch. .. container:: example >>> abjad.NamedPitch("cs''") - abjad.NamedPitch("b'") NamedInterval('-M2') >>> abjad.NamedPitch("cs''") - abjad.NamedPitch("fs''") NamedInterval('+P4') Returns named interval. ''' import abjad if isinstance(argument, type(self)): return abjad.NamedInterval.from_pitch_carriers(self, argument) interval = abjad.NamedInterval(argument) interval = -interval return interval.transpose(self)
def transpose(self, n=0): r'''Transposes named pitch by index `n`. .. container:: example Transposes C4 up a minor second: >>> abjad.NamedPitch("c'").transpose(n='m2') NamedPitch("df'") .. container:: example Transposes C4 down a major second: >>> abjad.NamedPitch("c'").transpose(n='-M2') NamedPitch('bf') Returns new named pitch. ''' import abjad interval = abjad.NamedInterval(n) return interval.transpose(self)
def transpose(self, n=0): """ Transposes named pitch by index `n`. .. container:: example Transposes C4 up a minor second: >>> abjad.NamedPitch("c'").transpose(n='m2') NamedPitch("df'") .. container:: example Transposes C4 down a major second: >>> abjad.NamedPitch("c'").transpose(n='-M2') NamedPitch('bf') Returns new named pitch. """ import abjad interval = abjad.NamedInterval(n) pitch_number = self.number + interval.semitones diatonic_pc_number = self._get_diatonic_pc_number() diatonic_pc_number += interval.staff_spaces diatonic_pc_number %= 7 diatonic_pc_name = \ constants._diatonic_pc_number_to_diatonic_pc_name[ diatonic_pc_number] pc = constants._diatonic_pc_name_to_pitch_class_number[ diatonic_pc_name ] nearest_neighbor = self._to_nearest_octave(pitch_number, pc) semitones = pitch_number - nearest_neighbor accidental = abjad.Accidental(semitones) octave = int(math.floor((pitch_number - semitones) / 12)) + 4 octave = abjad.Octave(octave) name = diatonic_pc_name + str(accidental) + octave.ticks return type(self)(name)
def trill_spanner( *tweaks: abjad.TweakInterface, alteration: str = None, harmonic: bool = None, left_broken: bool = None, map: abjad.Expression = None, right_broken: bool = None, selector: abjad.Expression = classes.select().tleaves().rleak(), start_trill_span: abjad.StartTrillSpan = None, stop_trill_span: abjad.StopTrillSpan = None, ) -> SpannerIndicatorCommand: r""" Attaches trill spanner indicators. .. container:: example Attaches trill spanner to trimmed leaves (leaked to the right): >>> stack = baca.stack( ... baca.figure( ... [1, 1, 5, -1], ... 16, ... affix=baca.rests_around([2], [4]), ... restart_talea=True, ... treatments=[-1], ... ), ... rmakers.beam(), ... baca.trill_spanner(), ... baca.tuplet_bracket_staff_padding(2), ... ) >>> selection = stack([[0, 2, 10], [18, 16, 15, 20, 19], [9]]) >>> lilypond_file = abjad.LilyPondFile.rhythm(selection) >>> rmakers.attach_markup_struts(lilypond_file) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(lilypond_file[abjad.Score]) >>> print(string) \new Score << \new GlobalContext { \time 11/8 s1 * 11/8 } \new Staff { \tweak text #tuplet-number::calc-fraction-text \times 9/10 { \override TupletBracket.staff-padding = 2 r8 - \tweak staff-padding 11 - \tweak transparent ##t ^ \markup I c'16 [ \startTrillSpan d'16 ] bf'4 ~ bf'16 r16 } \tweak text #tuplet-number::calc-fraction-text \times 9/10 { fs''16 [ e''16 ] ef''4 ~ ef''16 r16 af''16 [ g''16 ] } \times 4/5 { a'16 r4 \stopTrillSpan \revert TupletBracket.staff-padding } } >> .. container:: example Attaches trill to trimmed leaves (leaked to the right) in every run: >>> stack = baca.stack( ... baca.figure( ... [1, 1, 5, -1], ... 16, ... affix=baca.rests_around([2], [4]), ... restart_talea=True, ... treatments=[-1], ... ), ... rmakers.beam(), ... baca.new( ... baca.trill_spanner(), ... map=baca.runs(), ... ), ... baca.tuplet_bracket_staff_padding(2), ... ) >>> selection = stack([[0, 2, 10], [18, 16, 15, 20, 19], [9]]) >>> lilypond_file = abjad.LilyPondFile.rhythm(selection) >>> rmakers.attach_markup_struts(lilypond_file) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(lilypond_file[abjad.Score]) >>> print(string) \new Score << \new GlobalContext { \time 11/8 s1 * 11/8 } \new Staff { \tweak text #tuplet-number::calc-fraction-text \times 9/10 { \override TupletBracket.staff-padding = 2 r8 - \tweak staff-padding 11 - \tweak transparent ##t ^ \markup I c'16 [ \startTrillSpan d'16 ] bf'4 ~ bf'16 r16 \stopTrillSpan } \tweak text #tuplet-number::calc-fraction-text \times 9/10 { fs''16 [ \startTrillSpan e''16 ] ef''4 ~ ef''16 r16 \stopTrillSpan af''16 [ \startTrillSpan g''16 \stopTrillSpan ] } \times 4/5 { a'16 \startTrillSpan r4 \stopTrillSpan \revert TupletBracket.staff-padding } } >> .. container:: example Tweaks trill spanner: >>> stack = baca.stack( ... baca.figure( ... [1, 1, 5, -1], ... 16, ... affix=baca.rests_around([2], [4]), ... restart_talea=True, ... treatments=[-1], ... ), ... rmakers.beam(), ... baca.new( ... baca.trill_spanner( ... abjad.tweak("#red").color, ... alteration='M2', ... ), ... ), ... baca.tuplet_bracket_staff_padding(2), ... ) >>> selection = stack([[0, 2, 10], [18, 16, 15, 20, 19], [9]]) >>> lilypond_file = abjad.LilyPondFile.rhythm(selection) >>> rmakers.attach_markup_struts(lilypond_file) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(lilypond_file[abjad.Score]) >>> print(string) \new Score << \new GlobalContext { \time 11/8 s1 * 11/8 } \new Staff { \tweak text #tuplet-number::calc-fraction-text \times 9/10 { \override TupletBracket.staff-padding = 2 r8 - \tweak staff-padding 11 - \tweak transparent ##t ^ \markup I \pitchedTrill c'16 [ - \tweak color #red \startTrillSpan d' d'16 ] bf'4 ~ bf'16 r16 } \tweak text #tuplet-number::calc-fraction-text \times 9/10 { fs''16 [ e''16 ] ef''4 ~ ef''16 r16 af''16 [ g''16 ] } \times 4/5 { a'16 r4 \stopTrillSpan \revert TupletBracket.staff-padding } } >> """ if alteration is not None: prototype = (abjad.NamedPitch, abjad.NamedInterval, str) if not isinstance(alteration, prototype): message = "trill spanner 'alteration' must be pitch, interval, str:" message += f"\n {alteration}" raise Exception(message) interval = pitch = None if alteration is not None: try: pitch = abjad.NamedPitch(alteration) except Exception: try: interval = abjad.NamedInterval(alteration) except Exception: pass start_trill_span = start_trill_span or abjad.StartTrillSpan() if pitch is not None or interval is not None: start_trill_span = abjad.new(start_trill_span, interval=interval, pitch=pitch) if harmonic is True: string = "#(lambda (grob) (grob-interpret-markup grob" string += r' #{ \markup \musicglyph #"noteheads.s0harmonic" #}))' abjad.tweak(start_trill_span).TrillPitchHead.stencil = string stop_trill_span = stop_trill_span or abjad.StopTrillSpan() return SpannerIndicatorCommand( left_broken=left_broken, map=map, right_broken=right_broken, selector=selector, start_indicator=start_trill_span, stop_indicator=stop_trill_span, tags=[_site(inspect.currentframe())], tweaks=tweaks, )
def transpose(self, expr): r'''Transposes music specifier. :: >>> music_specifier = tsmakers.MusicSpecifier( ... pitch_handler=tsmakers.AbsolutePitchHandler( ... pitch_specifier = tsmakers.PitchSpecifier( ... pitch_segments=( ... "c' e' g'", ... "fs' gs'", ... "b", ... ), ... ratio=(1, 2, 3), ... ), ... ), ... ) >>> transposed_music_specifier = music_specifier.transpose('-M2') >>> print(format(transposed_music_specifier)) tsmakers.MusicSpecifier( pitch_handler=tsmakers.AbsolutePitchHandler( pitch_specifier=tsmakers.PitchSpecifier( pitch_segments=( abjad.PitchSegment( ( abjad.NamedPitch('bf'), abjad.NamedPitch("d'"), abjad.NamedPitch("f'"), ), item_class=abjad.NamedPitch, ), abjad.PitchSegment( ( abjad.NamedPitch("e'"), abjad.NamedPitch("fs'"), ), item_class=abjad.NamedPitch, ), abjad.PitchSegment( ( abjad.NamedPitch('a'), ), item_class=abjad.NamedPitch, ), ), ratio=abjad.Ratio((1, 2, 3)), ), ), ) Returns new music specifier. ''' if isinstance(expr, str): try: pitch = abjad.NamedPitch(expr) expr = abjad.NamedPitch('C4') - pitch except: expr = abjad.NamedInterval(expr) pitch_handler = self.pitch_handler if pitch_handler is not None: pitch_handler = pitch_handler.transpose(expr) return abjad.new( self, pitch_handler=pitch_handler, )
for handler, staff in zip(handlers_3, quartet_group): handler(staff) moment = "#(ly:make-moment 1 10)" abjad.setting(score).proportional_notation_duration = moment block = abjad.Block(name="score") block.items.append(score) style = '"dodecaphonic"' layout = abjad.Block(name="layout") layout.items.append(rf"\accidentalStyle {style}") file = abjad.LilyPondFile(items=[ r'\include "/Users/gregoryevans/abjad/abjad/_stylesheets/ekmelos-ji-accidental-markups.ily"', r'\include "/Users/gregoryevans/scores/polillas/polillas/build/score_stylesheet.ily"', layout, block, ]) evans.make_sc_file( score=score, tempo=tempo_pair, current_directory=pathlib.Path(__file__).parent, ) abjad.mutate.transpose(group_2, abjad.NamedInterval("+P8")) abjad.show(file)
def respell_accidentals( selection: abjad.Selection, *, include_multiples: bool = False, respell_by_pitch_class: bool = False, ) -> None: r"""Mutates an input |abjad.Selection| in place and has no return value; this function changes the accidentals of individual pitches of all chords in a container in order to avoid augmented unisons. Basic usage: To use this function, apply it to a selection that contains chords that have augmented unisons. >>> container = abjad.Container(r"c'4 r4 <ef' e'>4 g'4 <c' cs'>4 r2.") >>> auxjad.mutate(container[:]).respell_accidentals() >>> abjad.f(container) { c'4 r4 <ds' e'>4 g'4 <c' df'>4 r2. } .. figure:: ../_images/respell_accidentals-x33afbbamt.png .. note:: Auxjad automatically adds this function as an extension method to |abjad.mutate()|. It can thus be used from either :func:`auxjad.mutate()` or |abjad.mutate()|. Therefore, the two lines below are equivalent: >>> auxjad.mutate(staff[:]).respell_accidentals() >>> abjad.mutate(staff[:]).respell_accidentals() 2-note chords: The example below shows the default spelling of 2-note chords in Abjad in the upper staff, and the respelt 2-note chords in the bottom staff. >>> staff1 = abjad.Staff() >>> staff2 = abjad.Staff() >>> for pitch in range(12): ... staff1.append(abjad.Chord([pitch, pitch + 1], (1, 16))) ... staff2.append(abjad.Chord([pitch, pitch + 1], (1, 16))) >>> auxjad.mutate(staff2[:]).respell_accidentals() >>> literal = abjad.LilyPondLiteral(r'\accidentalStyle dodecaphonic') >>> abjad.attach(literal, staff1) >>> abjad.attach(literal, staff2) >>> score = abjad.Score([staff1, staff2]) >>> abjad.f(score) \new Score << \new Staff { \accidentalStyle dodecaphonic <c' cs'>16 <cs' d'>16 <d' ef'>16 <ef' e'>16 <e' f'>16 <f' fs'>16 <fs' g'>16 <g' af'>16 <af' a'>16 <a' bf'>16 <bf' b'>16 <b' c''>16 } \new Staff { \accidentalStyle dodecaphonic <c' df'>16 <cs' d'>16 <d' ef'>16 <ds' e'>16 <e' f'>16 <f' gf'>16 <fs' g'>16 <g' af'>16 <gs' a'>16 <a' bf'>16 <as' b'>16 <b' c''>16 } >> .. figure:: ../_images/respell_accidentals-jvg032q24il.png augmented unissons in larger chords: The function looks for all augmented unissons in chords of 3 or more pitches: >>> container1 = abjad.Container(r"<a c' cs' f'>1") >>> container2 = abjad.Container(r"<a c' cs' f'>1") >>> auxjad.mutate(container2[:]).respell_accidentals() >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <a c' cs' f'>1 } { <a c' df' f'>1 } } .. figure:: ../_images/respell_accidentals-gyficck05p.png It is not a problem if the pitches are input out of order. >>> container1 = abjad.Container(r"<e' cs' g' ef'>1") >>> container2 = abjad.Container(r"<e' cs' g' ef'>1") >>> auxjad.mutate(container2[:]).respell_accidentals() >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <cs' ef' e' g'>1 } { <cs' ds' e' g'>1 } } .. figure:: ../_images/respell_accidentals-xbu6u6mu6qo.png ``include_multiples``: By default, this function only changes spelling for pitches that are 1 semitone apart. >>> container1 = abjad.Container(r"<c' cs''>1") >>> container2 = abjad.Container(r"<c' cs''>1") >>> auxjad.mutate(container2[:]).respell_accidentals() >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <c' cs''>1 } { <c' cs''>1 } } .. figure:: ../_images/respell_accidentals-uszf11qb72d.png To consider pitches in different octaves (thus including augmented unisons, augmented octaves, augmented fifteenths, etc.), call this function with the keyword argument ``include_multiples`` set to ``True``. >>> container1 = abjad.Container(r"<c' cs''>1") >>> container2 = abjad.Container(r"<c' cs''>1") >>> auxjad.mutate(container2[:]).respell_accidentals( ... include_multiples=True, ... ) >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <c' cs''>1 } { <c' df''>1 } } .. figure:: ../_images/respell_accidentals-8am8cu2rmgi.png ``respell_by_pitch_class``: By default, when this function changes the spelling of a pitch, it does not change the spelling of all other pitches with the same pitch-class. >>> container1 = abjad.Container(r"<c' cs' cs''>1") >>> container2 = abjad.Container(r"<c' cs' cs''>1") >>> auxjad.mutate(container2[:]).respell_accidentals() >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <c' cs' cs''>1 } { <c' df' cs''>1 } } .. figure:: ../_images/respell_accidentals-47d16xk6gvs.png To alter all pitch-classes, call this function with the keyword argument ``respell_by_pitch_class`` set to ``True``. >>> container1 = abjad.Container(r"<c' cs' cs''>1") >>> container2 = abjad.Container(r"<c' cs' cs''>1") >>> auxjad.mutate(container2[:]).respell_accidentals( ... respell_by_pitch_class=True, ... ) >>> staff = abjad.Staff([container1, container2]) >>> abjad.f(staff) \new Staff { { <c' cs' cs''>1 } { <c' df' df''>1 } } .. figure:: ../_images/respell_accidentals-kobft0oq9sl.png """ if not isinstance(selection, abjad.Selection): raise TypeError("argument must be 'abjad.Selection'") if not isinstance(respell_by_pitch_class, bool): raise TypeError("'respell_by_pitch_class' must be 'bool'") if not isinstance(include_multiples, bool): raise TypeError("'include_multiples' must be 'bool'") for leaf in selection.leaves(): if isinstance(leaf, abjad.Chord): accidentals = [pitch.accidental for pitch in leaf.written_pitches] if not include_multiples: # dealing only with intervals of size equal to 1 semitone for i in range(len(leaf.written_pitches) - 1): p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[i + 1] interval12 = p1 - p2 try: p3 = leaf.written_pitches[i + 2] interval23 = p2 - p3 except IndexError: p3 = None interval23 = None if (interval12 == abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+m2')): if not respell_by_pitch_class: # respelling only one single note if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): accidentals[i + 1] = abjad.Accidental('f') else: # respelling all matching pitch-classes if p1.accidental == abjad.Accidental('f'): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p1.pitch_class: accidentals[j] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p2.pitch_class: accidentals[j] = abjad.Accidental('f') else: # dealing with augmented unisons as well as augmented 8as, # 15ths, etc. for i in range(len(leaf.written_pitches) - 1): for j in range(i + 1, len(leaf.written_pitches)): # no p3 this time since p1 and p2 are not necessary # consecutive pitches in the chord p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[j] interval = abjad.NamedIntervalClass(p1 - p2) if (interval in ( abjad.NamedIntervalClass('+A1'), abjad.NamedIntervalClass('-d1'), )): # no need for respell_by_pitch_class since this # will go through all notes in the chord anyway if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') if p1.accidental == abjad.Accidental('s'): accidentals[i] = abjad.Accidental('f') elif p1.accidental == abjad.Accidental(''): if p2.accidental == abjad.Accidental('s'): accidentals[j] = abjad.Accidental('f') elif p2.accidental == abjad.Accidental('f'): accidentals[j] = abjad.Accidental('s') # rewritting chord with new spelling respelt_pitches = [] for pitch, accidental in zip(leaf.written_pitches, accidentals): if accidental == abjad.Accidental('f'): respelt_pitches.append(pitch._respell_with_flats()) elif accidental == abjad.Accidental('s'): respelt_pitches.append(pitch._respell_with_sharps()) else: respelt_pitches.append(pitch) leaf.written_pitches = respelt_pitches
def make_ji_bundle(pitch, ratio): r""" Makes JI bundle. .. container:: example >>> bundle = microtones.make_ji_bundle(abjad.NamedPitch("c'"), "3/2") >>> bundle.pitch NamedPitch("g'") >>> print(abjad.storage(bundle.vector)) microtones.JIVector( diatonic_accidental='natural', syntonic_commas_down=0, syntonic_commas_up=0, septimal_commas_down=0, septimal_commas_up=0, undecimal_quarter_tones_down=0, undecimal_quarter_tones_up=0, tridecimal_third_tones_down=0, tridecimal_third_tones_up=0, seventeen_limit_schismas_down=0, seventeen_limit_schismas_up=0, nineteen_limit_schismas_down=0, nineteen_limit_schismas_up=0, twenty_three_limit_commas_down=0, twenty_three_limit_commas_up=0, ) """ if isinstance(pitch, str): pitch = abjad.NamedPitch(pitch) elif isinstance(pitch, int): pitch = abjad.NumberedPitch(pitch) ratio = quicktions.Fraction(ratio) numerator_factors = _prime_factors(ratio.numerator) denominator_factors = _prime_factors(ratio.denominator) accidental_vector = JIVector(diatonic_accidental=pitch.accidental.name) for prime in numerator_factors: assert prime <= 23 for string in _numerator_factor_to_intervals[prime]: pitch = abjad.NamedInterval(string).transpose(pitch) if prime in _numerator_factor_to_nudge: string = _numerator_factor_to_nudge[prime] value = getattr(accidental_vector, string) setattr(accidental_vector, string, value + 1) for prime in denominator_factors: assert prime <= 23 for string in _numerator_factor_to_intervals[prime]: string = string.replace("+", "-") pitch = abjad.NamedInterval(string).transpose(pitch) if prime in _numerator_factor_to_nudge: string = _numerator_factor_to_nudge[prime] if string.endswith("_up"): string = string.replace("_up", "_down") else: string = string.replace("_down", "_up") value = getattr(accidental_vector, string) setattr(accidental_vector, string, value + 1) accidental_vector.diatonic_accidental = pitch.accidental.name return JIBundle(pitch, accidental_vector)
def respell_augmented_unisons( selection: abjad.Selection, *, include_multiples: bool = False, respell_by_pitch_class: bool = False, ) -> None: r"""Mutates an input |abjad.Selection| in place and has no return value; this function changes the accidentals of individual pitches of all chords in a container in order to avoid augmented unisons. Basic usage: To use this function, apply it to a selection that contains chords that have augmented unisons. >>> container = abjad.Container(r"c'4 r4 <ef' e'>4 g'4 <c' cs'>4 r2.") >>> abjad.show(container) .. docs:: { c'4 r4 <ef' e'>4 g'4 <c' cs'>4 r2. } .. figure:: ../_images/respell_augmented_unisons-OXnGvQzGT2.png >>> auxjad.mutate.respell_augmented_unisons(container[:]) >>> abjad.show(container) .. docs:: { c'4 r4 <ds' e'>4 g'4 <c' df'>4 r2. } .. figure:: ../_images/respell_augmented_unisons-x33afbbamt.png This can be useful when using tuples of integers to create chords that contain minor seconds: >>> pitches = [(0, 1), (8, 9, 12), (0, 4, 5, 6), (-1, 5, 6)] >>> durations = [(1, 8), (3, 8), (7, 16), (1, 16)] >>> maker = abjad.LeafMaker() >>> chords = maker(pitches, durations) >>> staff = abjad.Staff(chords) >>> literal = abjad.LilyPondLiteral(r'\accidentalStyle dodecaphonic') >>> abjad.attach(literal, staff) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' cs'>8 <af' a' c''>4. <c' e' f' fs'>4.. <b f' fs'>16 } .. figure:: ../_images/respell_augmented_unisons-mWVWwV9uBx.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' df'>8 <gs' a' c''>4. <c' e' f' gf'>4.. <b f' gf'>16 } .. figure:: ../_images/respell_augmented_unisons-IfzaseW4oS.png .. note:: Auxjad automatically adds this function as an extension function to |abjad.mutate|. It can thus be used from either |auxjad.mutate|_ or |abjad.mutate| namespaces. Therefore, the two lines below are equivalent: >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.mutate.respell_augmented_unisons(staff[:]) 2-note chords: The example below shows first the default spelling of 2-note chords in Abjad followed by the respelt 2-note chords. >>> staff = abjad.Staff() >>> for pitch in range(12): ... staff.append(abjad.Chord([pitch, pitch + 1], (1, 16))) >>> literal = abjad.LilyPondLiteral(r'\accidentalStyle dodecaphonic') >>> abjad.attach(literal, staff) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' cs'>16 <cs' d'>16 <d' ef'>16 <ef' e'>16 <e' f'>16 <f' fs'>16 <fs' g'>16 <g' af'>16 <af' a'>16 <a' bf'>16 <bf' b'>16 <b' c''>16 } .. figure:: ../_images/respell_augmented_unisons-qQduIqCRpz.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' df'>16 <cs' d'>16 <d' ef'>16 <ds' e'>16 <e' f'>16 <f' gf'>16 <fs' g'>16 <g' af'>16 <gs' a'>16 <a' bf'>16 <as' b'>16 <b' c''>16 } .. figure:: ../_images/respell_augmented_unisons-jvg032q24il.png augmented unissons in chords with 3 or more pitches: The function looks for all augmented unissons in chords of 3 or more pitches: >>> staff = abjad.Staff(r"<a c' cs' f'>1") >>> abjad.show(staff) .. docs:: \new Staff { <a c' cs' f'>1 } .. figure:: ../_images/respell_augmented_unisons-IklJO81q1E.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <a c' df' f'>1 } .. figure:: ../_images/respell_augmented_unisons-gyficck05p.png ``include_multiples``: By default, this function only changes spelling for pitches that are 1 semitone apart. >>> staff = abjad.Staff(r"<c' cs''>1") >>> abjad.show(staff) .. docs:: \new Staff { <c' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-HPqFrADjeh.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <c' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-uszf11qb72d.png To consider pitches in different octaves (thus including augmented unisons, augmented octaves, augmented fifteenths, etc.), call this function with the keyword argument ``include_multiples`` set to ``True``. >>> staff = abjad.Staff(r"<c' cs''>1") >>> auxjad.mutate.respell_augmented_unisons( ... staff[:], ... include_multiples=True, ... ) .. docs:: \new Staff { <c' df''>1 } .. figure:: ../_images/respell_augmented_unisons-8am8cu2rmgi.png ``respell_by_pitch_class``: By default, when this function changes the spelling of a pitch, it does not change the spelling of all other pitches with the same pitch-class. >>> staff = abjad.Staff(r"<c' cs' cs''>1") >>> abjad.show(staff) .. docs:: \new Staff { <c' cs' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-eWixL7iCEq.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <c' df' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-47d16xk6gvs.png To alter all pitch-classes, call this function with the keyword argument ``respell_by_pitch_class`` set to ``True``. >>> staff = abjad.Staff(r"<c' cs' cs''>1") >>> auxjad.mutate.respell_augmented_unisons( ... staff[:], ... respell_by_pitch_class=True, ... ) >>> abjad.show(staff) .. docs:: \new Staff { <c' df' df''>1 } .. figure:: ../_images/respell_augmented_unisons-kobft0oq9sl.png """ if not isinstance(selection, abjad.Selection): raise TypeError("argument must be 'abjad.Selection'") if not isinstance(respell_by_pitch_class, bool): raise TypeError("'respell_by_pitch_class' must be 'bool'") if not isinstance(include_multiples, bool): raise TypeError("'include_multiples' must be 'bool'") for leaf in selection.leaves(): if isinstance(leaf, abjad.Chord): accidentals = [pitch.accidental for pitch in leaf.written_pitches] original_accidentals = accidentals[:] if not include_multiples: # dealing only with intervals of size equal to 1 semitone for i in range(len(leaf.written_pitches) - 1): p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[i + 1] interval12 = p1 - p2 try: p3 = leaf.written_pitches[i + 2] interval23 = p2 - p3 except IndexError: p3 = None interval23 = None if (interval12 == abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+m2')): if not respell_by_pitch_class: # respelling only one single note if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): accidentals[i + 1] = abjad.Accidental('f') else: # respelling all matching pitch-classes if p1.accidental == abjad.Accidental('f'): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p1.pitch_class: accidentals[j] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p2.pitch_class: accidentals[j] = abjad.Accidental('f') else: # dealing with augmented unisons as well as augmented 8as, # 15ths, etc. for i in range(len(leaf.written_pitches) - 1): for j in range(i + 1, len(leaf.written_pitches)): # no p3 this time since p1 and p2 are not necessary # consecutive pitches in the chord p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[j] interval = abjad.NamedIntervalClass(p1 - p2) if (interval in ( abjad.NamedIntervalClass('+A1'), abjad.NamedIntervalClass('-d1'), )): # no need for respell_by_pitch_class since this # will go through all notes in the chord anyway if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') if p1.accidental == abjad.Accidental('s'): accidentals[i] = abjad.Accidental('f') elif p1.accidental == abjad.Accidental(''): if p2.accidental == abjad.Accidental('s'): accidentals[j] = abjad.Accidental('f') elif p2.accidental == abjad.Accidental('f'): accidentals[j] = abjad.Accidental('s') # rewritting chord with new spelling respelt_pitches = [] for pitch, accidental, original_accidental in zip( leaf.written_pitches, accidentals, original_accidentals, ): if (accidental != original_accidental and accidental == abjad.Accidental('f')): respelt_pitches.append(pitch._respell(accidental='flats')) elif (accidental != original_accidental and accidental == abjad.Accidental('s')): respelt_pitches.append(pitch._respell(accidental='sharps')) else: respelt_pitches.append(pitch) leaf.written_pitches = respelt_pitches