Example #1
0
 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
Example #2
0
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
Example #3
0
    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)
Example #4
0
 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
Example #5
0
    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,
        )
Example #6
0
    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
Example #7
0
 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
Example #8
0
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)
Example #9
0
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
Example #10
0
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
Example #11
0
    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)
Example #12
0
    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[:]
Example #13
0
    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)
Example #14
0
    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)
Example #15
0
    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)
Example #16
0
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,
            )
Example #18
0
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)
Example #19
0
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
Example #20
0
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