"""
The rmakers functions.
"""
import inspect
import math
import typing
import abjad
from . import classes as _classes
def _function_name(frame):
function_name = frame.f_code.co_name
string = f"rmakers.{function_name}()"
return abjad.Tag(string)
def _interpolate_cosine(y1, y2, mu) -> float:
mu2 = (1 - math.cos(mu * math.pi)) / 2
return y1 * (1 - mu2) + y2 * mu2
def _interpolate_divide_multiple(
total_durations, reference_durations, exponent="cosine"
) -> list[float]:
"""
Interpolates ``reference_durations`` such that the sum of the resulting
interpolated values equals the given ``total_durations``.
.. container:: example
>>> durations = rmakers.functions._interpolate_divide_multiple(
... total_durations=[100, 50],
... reference_durations=[20, 10, 20],
... )
>>> for duration in durations:
... duration
19.448...
18.520...
16.227...
13.715...
11.748...
10.487...
9.8515...
9.5130...
10.421...
13.073...
16.991...
Precondition: ``len(totals_durations) == len(reference_durations)-1``.
Set ``exponent`` to ``cosine`` for cosine interpolation. Set ``exponent`` to a
number for exponential interpolation.
"""
assert len(total_durations) == len(reference_durations) - 1
durations = []
for i in range(len(total_durations)):
durations_ = _interpolate_divide(
total_durations[i],
reference_durations[i],
reference_durations[i + 1],
exponent,
)
for duration_ in durations_:
assert isinstance(duration_, float)
durations.append(duration_)
return durations
def _interpolate_exponential(y1, y2, mu, exponent=1) -> float:
"""
Interpolates between ``y1`` and ``y2`` at position ``mu``.
.. container:: example
Exponents equal to 1 leave durations unscaled:
>>> for mu in (0, 0.25, 0.5, 0.75, 1):
... rmakers.functions._interpolate_exponential(100, 200, mu, exponent=1)
...
100
125.0
150.0
175.0
200
Exponents greater than 1 generate ritardandi:
>>> for mu in (0, 0.25, 0.5, 0.75, 1):
... rmakers.functions._interpolate_exponential(100, 200, mu, exponent=2)
...
100
106.25
125.0
156.25
200
Exponents less than 1 generate accelerandi:
>>> for mu in (0, 0.25, 0.5, 0.75, 1):
... rmakers.functions._interpolate_exponential(100, 200, mu, exponent=0.5)
...
100.0
150.0
170.71067811865476
186.60254037844388
200.0
"""
result = y1 * (1 - mu**exponent) + y2 * mu**exponent
return result
def _interpolate_divide(
total_duration, start_duration, stop_duration, exponent="cosine"
) -> str | list[float]:
"""
Divides ``total_duration`` into durations computed from interpolating between
``start_duration`` and ``stop_duration``.
.. container:: example
>>> rmakers.functions._interpolate_divide(
... total_duration=10,
... start_duration=1,
... stop_duration=1,
... exponent=1,
... )
[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
>>> sum(_)
10.0
>>> rmakers.functions._interpolate_divide(
... total_duration=10,
... start_duration=5,
... stop_duration=1,
... )
[4.798..., 2.879..., 1.326..., 0.995...]
>>> sum(_)
10.0
Set ``exponent`` to ``'cosine'`` for cosine interpolation.
Set ``exponent`` to a numeric value for exponential interpolation with
``exponent`` as the exponent.
Scales resulting durations so that their sum equals ``total_duration`` exactly.
"""
if total_duration <= 0:
message = "Total duration must be positive."
raise ValueError(message)
if start_duration <= 0 or stop_duration <= 0:
message = "Both 'start_duration' and 'stop_duration'"
message += " must be positive."
raise ValueError(message)
if total_duration < (stop_duration + start_duration):
return "too small"
durations = []
total_duration = float(total_duration)
partial_sum = 0.0
while partial_sum < total_duration:
if exponent == "cosine":
duration = _interpolate_cosine(
start_duration, stop_duration, partial_sum / total_duration
)
else:
duration = _interpolate_exponential(
start_duration,
stop_duration,
partial_sum / total_duration,
exponent,
)
durations.append(duration)
partial_sum += duration
durations = [_ * total_duration / sum(durations) for _ in durations]
return durations
def _is_accelerando(argument):
first_leaf = abjad.select.leaf(argument, 0)
last_leaf = abjad.select.leaf(argument, -1)
first_duration = abjad.get.duration(first_leaf)
last_duration = abjad.get.duration(last_leaf)
if last_duration < first_duration:
return True
return False
def _is_ritardando(argument):
first_leaf = abjad.select.leaf(argument, 0)
last_leaf = abjad.select.leaf(argument, -1)
first_duration = abjad.get.duration(first_leaf)
last_duration = abjad.get.duration(last_leaf)
if first_duration < last_duration:
return True
return False
def _make_beamable_groups(components, durations):
assert all(isinstance(_, abjad.Duration) for _ in durations)
music_duration = abjad.get.duration(components)
if music_duration != sum(durations):
message = f"music duration {music_duration} does not equal"
message += f" total duration {sum(durations)}:\n"
message += f" {components}\n"
message += f" {durations}"
raise Exception(message)
component_to_timespan = []
start_offset = abjad.Offset(0)
for component in components:
duration = abjad.get.duration(component)
stop_offset = start_offset + duration
timespan = abjad.Timespan(start_offset, stop_offset)
pair = (component, timespan)
component_to_timespan.append(pair)
start_offset = stop_offset
group_to_target_duration = []
start_offset = abjad.Offset(0)
for target_duration in durations:
stop_offset = start_offset + target_duration
group_timespan = abjad.Timespan(start_offset, stop_offset)
start_offset = stop_offset
group = []
for component, component_timespan in component_to_timespan:
if component_timespan in group_timespan:
group.append(component)
pair = ([group], target_duration)
group_to_target_duration.append(pair)
beamable_groups = []
for group, target_duration in group_to_target_duration:
group_duration = abjad.get.duration(group)
assert group_duration <= target_duration
if group_duration == target_duration:
beamable_groups.append(group)
else:
beamable_groups.append([])
return beamable_groups
def _make_time_signature_staff(time_signatures):
assert time_signatures, repr(time_signatures)
staff = abjad.Staff(simultaneous=True)
score = abjad.Score([staff], name="Score")
time_signature_voice = abjad.Voice(name="TimeSignatureVoice")
staff.append(time_signature_voice)
staff.append(abjad.Voice(name="RhythmMaker.Music"))
for time_signature in time_signatures:
duration = time_signature.pair
skip = abjad.Skip(1, multiplier=duration)
time_signature_voice.append(skip)
abjad.attach(time_signature, skip, context="Staff")
return score
def _validate_tuplets(argument):
for tuplet in abjad.iterate.components(argument, abjad.Tuplet):
assert abjad.Duration(tuplet.multiplier).normalized(), repr(tuplet)
assert len(tuplet), repr(tuplet)
[docs]def after_grace_container(
argument: abjad.Component | typing.Sequence[abjad.Component],
counts: typing.Sequence[int],
*,
beam: bool = False,
slash: bool = False,
talea: _classes.Talea = _classes.Talea([1], 8),
) -> None:
r"""
Makes (and attaches) after-grace containers.
.. container:: example
>>> def make_lilypond_file(pairs, *, beam=False, slash=False):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.note(_, -1) for _ in tuplets]
... rmakers.after_grace_container(notes, [1, 4], beam=beam, slash=slash)
... rmakers.extract_trivial(voice)
... score = lilypond_file["Score"]
... abjad.setting(score).autoBeaming = False
... return lilypond_file
.. container:: example
With ``beam=False`` and ``slash=False``:
>>> pairs = [(3, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs, beam=False, slash=False)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
c'4
c'4
c'4
\afterGrace
c'4
{
c'8
}
}
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
c'4
c'4
c'4
c'4
\afterGrace
c'4
{
c'8
c'8
c'8
c'8
}
}
}
}
}
.. container:: example
With ``beam=True`` and ``slash=True``:
>>> pairs = [(3, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs, beam=True, slash=True)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
c'4
c'4
c'4
\afterGrace
c'4
{
c'8
}
}
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
c'4
c'4
c'4
c'4
\afterGrace
c'4
{
\slash
c'8
[
c'8
c'8
c'8
]
}
}
}
}
}
When ``slash=True`` then ``beam`` must also be true.
Leaves lone after-graces unslashed even when ``slash=True``.
"""
assert all(isinstance(_, int) for _ in counts), repr(counts)
if slash is True:
assert beam is True, repr(beam)
assert isinstance(talea, _classes.Talea), repr(talea)
leaves = abjad.select.leaves(argument, grace=False)
cyclic_counts = abjad.CyclicTuple(counts)
start = 0
for i, leaf in enumerate(leaves):
count = cyclic_counts[i]
if not count:
continue
stop = start + count
durations = talea[start:stop]
notes = abjad.makers.make_leaves([0], durations)
container = abjad.AfterGraceContainer(notes)
abjad.attach(container, leaf)
if 1 < len(notes):
if beam is True:
abjad.beam(notes)
if slash is True:
literal = abjad.LilyPondLiteral(r"\slash", site="before")
abjad.attach(literal, notes[0])
[docs]def attach_time_signatures(
voice: abjad.Voice,
time_signatures: list[abjad.TimeSignature],
) -> None:
leaves = abjad.select.leaves(voice, grace=False)
durations = [_.duration for _ in time_signatures]
parts = abjad.select.partition_by_durations(leaves, durations)
assert len(parts) == len(time_signatures)
previous_time_signature = None
for time_signature, part in zip(time_signatures, parts):
assert isinstance(time_signature, abjad.TimeSignature)
if time_signature != previous_time_signature:
leaf = abjad.select.leaf(part, 0)
abjad.detach(abjad.TimeSignature, leaf)
abjad.attach(time_signature, leaf)
previous_time_signature = time_signature
[docs]def beam(
argument,
*,
beam_lone_notes: bool = False,
beam_rests: bool = False,
stemlet_length: int | float | None = None,
tag: abjad.Tag | None = None,
) -> None:
r"""
Beams runs of notes in each component in ``argument``.
.. container:: example
>>> def make_lilypond_file(pairs, beam_rests=False, stemlet_length=None):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 1, 1, -1], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(
... voice, beam_rests=beam_rests, stemlet_length=stemlet_length
... )
... rmakers.swap_trivial(voice)
... score = lilypond_file["Score"]
... abjad.setting(score).autoBeaming = False
... return lilypond_file
.. container:: example
Beams runs of notes in each tuplet:
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
{
\time 3/8
c'16
[
c'16
c'16
]
r16
c'16
[
c'16
]
}
{
\time 4/8
c'16
r16
c'16
[
c'16
c'16
]
r16
c'16
[
c'16
]
}
{
\time 3/8
c'16
r16
c'16
[
c'16
c'16
]
r16
}
{
\time 4/8
c'16
[
c'16
c'16
]
r16
c'16
[
c'16
c'16
]
r16
}
}
}
}
.. container:: example
Set ``beam_rests=True`` and ``stemlet_length=n`` to beam rests with
stemlets of length ``n``:
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(
... pairs, beam_rests=True, stemlet_length=0.75
... )
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
{
\override RhythmicStaff.Stem.stemlet-length = 0.75
\time 3/8
c'16
[
c'16
c'16
r16
c'16
c'16
]
\revert RhythmicStaff.Stem.stemlet-length
}
{
\override RhythmicStaff.Stem.stemlet-length = 0.75
\time 4/8
c'16
[
r16
c'16
c'16
c'16
r16
c'16
c'16
]
\revert RhythmicStaff.Stem.stemlet-length
}
{
\override RhythmicStaff.Stem.stemlet-length = 0.75
\time 3/8
c'16
[
r16
c'16
c'16
c'16
r16
]
\revert RhythmicStaff.Stem.stemlet-length
}
{
\override RhythmicStaff.Stem.stemlet-length = 0.75
\time 4/8
c'16
[
c'16
c'16
r16
c'16
c'16
c'16
r16
]
\revert RhythmicStaff.Stem.stemlet-length
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for item in argument:
unbeam(item)
leaves = abjad.select.leaves(item)
abjad.beam(
leaves,
beam_lone_notes=beam_lone_notes,
beam_rests=beam_rests,
stemlet_length=stemlet_length,
tag=tag,
)
[docs]def beam_groups(
argument,
*,
beam_lone_notes: bool = False,
beam_rests: bool = False,
stemlet_length: int | float | None = None,
tag: abjad.Tag | None = None,
) -> None:
r"""
Beams groups in ``argument`` with single span beam.
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam_groups(tuplets)
... rmakers.swap_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
{
\set stemLeftBeamCount = 0
\set stemRightBeamCount = 2
\time 3/8
c'16
[
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 1
c'16
}
{
\set stemLeftBeamCount = 1
\set stemRightBeamCount = 2
\time 4/8
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 1
c'16
}
{
\set stemLeftBeamCount = 1
\set stemRightBeamCount = 2
\time 3/8
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 1
c'16
}
{
\set stemLeftBeamCount = 1
\set stemRightBeamCount = 2
\time 4/8
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 2
c'16
\set stemLeftBeamCount = 2
\set stemRightBeamCount = 0
c'16
]
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
unbeam(argument)
durations = [abjad.get.duration(_) for _ in argument]
leaves = abjad.select.leaves(argument)
abjad.beam(
leaves,
beam_lone_notes=beam_lone_notes,
beam_rests=beam_rests,
durations=durations,
span_beam_count=1,
stemlet_length=stemlet_length,
tag=tag,
)
[docs]def before_grace_container(
argument: abjad.Component | typing.Sequence[abjad.Component],
counts: typing.Sequence[int],
*,
beam: bool = False,
slash: bool = False,
slur: bool = False,
talea: _classes.Talea = _classes.Talea([1], 8),
) -> None:
r"""
Makes (and attaches) before-grace containers.
With ``beam=False``, ``slash=False``, ``slur=False`` (default):
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(notes, [1, 2, 3])
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\grace {
c'8
}
c'4
\grace {
c'8
c'8
}
c'4
\grace {
c'8
c'8
c'8
}
c'4
c'4
}
}
}
}
.. container:: example
With ``beam=False``, ``slash=False``, ``slur=True``:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(notes, [1, 2, 3], slur=True)
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\appoggiatura {
c'8
}
c'4
\appoggiatura {
c'8
c'8
}
c'4
\appoggiatura {
c'8
c'8
c'8
}
c'4
c'4
}
}
}
}
.. container:: example
With ``beam=True``, ``slash=False``, ``slur=False``:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(notes, [1, 2, 3], beam=True)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\grace {
c'8
}
c'4
\grace {
c'8
[
c'8
]
}
c'4
\grace {
c'8
[
c'8
c'8
]
}
c'4
c'4
}
}
}
}
.. container:: example
With ``beam=True``, ``slash=False``, ``slur=True``:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(notes, [1, 2, 3], beam=True, slur=True)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\appoggiatura {
c'8
}
c'4
\appoggiatura {
c'8
[
c'8
]
}
c'4
\appoggiatura {
c'8
[
c'8
c'8
]
}
c'4
c'4
}
}
}
}
.. container:: example
With ``beam=True``, ``slash=True``, ``slur=False``:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(notes, [1, 2, 3], beam=True, slash=True)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\slashedGrace {
c'8
}
c'4
\slashedGrace {
\slash
c'8
[
c'8
]
}
c'4
\slashedGrace {
\slash
c'8
[
c'8
c'8
]
}
c'4
c'4
}
}
}
}
(When ``slash=True`` then ``beam`` must also be true.)
.. container:: example
With ``beam=True``, ``slash=True``, ``slur=True``:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... rmakers.before_grace_container(
... notes, [1, 2, 3], beam=True, slash=True, slur=True
... )
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> score = lilypond_file["Score"]
>>> abjad.setting(score).autoBeaming = False
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
autoBeaming = ##f
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
\acciaccatura {
c'8
}
c'4
\acciaccatura {
\slash
c'8
[
c'8
]
}
c'4
\acciaccatura {
\slash
c'8
[
c'8
c'8
]
}
c'4
c'4
}
}
}
}
(When ``slash=True`` then ``beam`` must also be true.)
"""
assert all(isinstance(_, int) for _ in counts), repr(counts)
if slash is True:
assert beam is True, repr(beam)
assert isinstance(talea, _classes.Talea), repr(talea)
leaves = abjad.select.leaves(argument, grace=False)
cyclic_counts = abjad.CyclicTuple(counts)
start = 0
for i, leaf in enumerate(leaves):
count = cyclic_counts[i]
if not count:
continue
stop = start + count
durations = talea[start:stop]
notes = abjad.makers.make_leaves([0], durations)
if len(notes) == 1:
if slash is False and slur is False:
command = r"\grace"
elif slash is False and slur is True:
command = r"\appoggiatura"
elif slash is True and slur is False:
command = r"\slashedGrace"
elif slash is True and slur is True:
command = r"\acciaccatura"
else:
raise Exception
elif 1 < len(notes):
if slash is True:
literal = abjad.LilyPondLiteral(r"\slash", site="before")
abjad.attach(literal, notes[0])
if slash is False and slur is False:
command = r"\grace"
elif slash is False and slur is True:
command = r"\appoggiatura"
elif slash is True and slur is False:
command = r"\slashedGrace"
elif slash is True and slur is True:
command = r"\acciaccatura"
else:
raise Exception
container = abjad.BeforeGraceContainer(notes, command=command)
abjad.attach(container, leaf)
if 1 < len(notes):
if beam is True:
abjad.beam(notes)
[docs]def denominator(argument, denominator: int | abjad.typings.Duration) -> None:
r"""
Sets tuplet ratio denominator of tuplets in ``argument``.
.. container:: example
>>> def make_lilypond_file(pairs, denominator=None):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.tuplet(durations, [(1, 4)])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.rewrite_dots(voice)
... rmakers.beam(voice)
... rmakers.force_fraction(voice)
... if denominator is not None:
... rmakers.denominator(voice, denominator)
... score = lilypond_file["Score"]
... abjad.override(score).TupletBracket.bracket_visibility = True
... abjad.override(score).TupletBracket.staff_padding = 4.5
... abjad.setting(score).tupletFullLength = True
... return lilypond_file
.. container:: example
By default, tuplet numerators and denominators are reduced to numbers
that are relatively prime. This means that ratios like ``6:4`` and
``10:8`` do not arise:
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 6/5
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
Spelling tuplet ratios in terms of a given duration.
.. container:: example
**16th notes.** This attempts to set the denominator of each tuplet
ratio in terms of sixteenth notes. Because the first tuplet is so
short, its ratio must be read as "5 in the time of 4 thirty-second
notes." But the ratios of the three longer tuplets can now be read
as "x in the time of y sixteenth notes":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, denominator=(1, 16))
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 6/5
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
**32nd notes.** This sets the denominator of each tuplet ratios in
terms of thirty-second notes. All tuplet ratios can now be read as
"x in the time of y thirty-second notes":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, denominator=(1, 32))
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 12/10
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 16/20
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
**64th notes.** This sets the denominator of each tuplet ratios in
terms of sixth-fourth notes. All tuplet ratios can now be read as
"x in the time of y sixty-fourth notes":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, (1, 64))
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 12/10
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 16/20
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
Spelling tuplet ratios with a fixed denominator.
.. container:: example
**Tuplet ratios spelled with denominator equal to 8.** The ratio of
the third tuplet is left unchanged. But the ratios of the other
tuplets can be spelled "x in the time of 8":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, 8)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 12/10
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 16/20
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
**Tuplet ratios spelled with denominator equal to 12.** The ratios
of all tuplets can be spelled "x in the time of 12":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, 12)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 12/10
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 16/20
{
\time 8/16
c'8
c'2
}
}
}
}
.. container:: example
**Tuplet ratios spelled with denominator equal to 13.** No tuplet
ratio can be spelled "x in the time of 13":
>>> pairs = [(2, 16), (4, 16), (6, 16), (8, 16)]
>>> lilypond_file = make_lilypond_file(pairs, 13)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/5
{
\time 2/16
c'32
[
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 8/10
{
\time 4/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 12/10
{
\time 6/16
c'16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 16/20
{
\time 8/16
c'8
c'2
}
}
}
}
"""
if isinstance(denominator, tuple):
denominator = abjad.Duration(denominator)
for tuplet in abjad.select.tuplets(argument):
if isinstance(denominator, abjad.Duration):
unit_duration = denominator
assert unit_duration.numerator == 1
duration = abjad.get.duration(tuplet)
denominator_ = unit_duration.denominator
pair = abjad.duration.with_denominator(duration, denominator_)
tuplet.denominator = pair[0]
elif abjad.math.is_positive_integer(denominator):
tuplet.denominator = denominator
else:
raise Exception(f"invalid preferred denominator: {denominator!r}.")
[docs]def duration_bracket(argument) -> None:
"""
Applies duration bracket to tuplets in ``argument``.
"""
for tuplet in abjad.select.tuplets(argument):
duration_ = abjad.get.duration(tuplet)
components = abjad.makers.make_leaves([0], [duration_])
if all(isinstance(_, abjad.Note) for _ in components):
durations = [abjad.get.duration(_) for _ in components]
strings = [_.lilypond_duration_string for _ in durations]
string = " ~ ".join(strings)
string = rf"\rhythm {{ {string} }}"
else:
string = abjad.illustrators.components_to_score_markup_string(components)
string = rf"\markup \scale #'(0.75 . 0.75) {string}"
abjad.override(tuplet).TupletNumber.text = string
[docs]def example(
components: typing.Sequence[abjad.Component],
time_signatures: typing.Sequence[abjad.TimeSignature],
*,
includes: typing.Sequence[str] = (),
) -> abjad.LilyPondFile:
"""
Makes example LilyPond file.
Function is a documentation helper.
"""
assert all(isinstance(_, abjad.Component) for _ in components), repr(components)
assert time_signatures is not None
assert all(isinstance(_, abjad.TimeSignature) for _ in time_signatures), repr(
time_signatures
)
assert all(isinstance(_, str) for _ in includes), repr(includes)
lilypond_file = abjad.illustrators.components(components, time_signatures)
includes = [rf'\include "{_}"' for _ in includes]
lilypond_file.items[0:0] = includes
staff = lilypond_file["Staff"]
staff.lilypond_type = "RhythmicStaff"
abjad.override(staff).Clef.stencil = False
return lilypond_file
[docs]def feather_beam(
argument,
*,
beam_rests: bool = False,
stemlet_length: int | float | None = None,
tag: abjad.Tag | None = None,
) -> None:
"""
Feather-beams leaves in ``argument``.
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for item in argument:
unbeam(item)
leaves = abjad.select.leaves(item)
abjad.beam(
leaves,
beam_rests=beam_rests,
stemlet_length=stemlet_length,
tag=tag,
)
for item in argument:
first_leaf = abjad.select.leaf(item, 0)
if _is_accelerando(item):
abjad.override(first_leaf).Beam.grow_direction = abjad.RIGHT
elif _is_ritardando(item):
abjad.override(first_leaf).Beam.grow_direction = abjad.LEFT
[docs]def force_augmentation(argument) -> None:
r"""
Spells tuplets in ``argument`` as augmentations.
.. container:: example
>>> def make_lilypond_file(pairs, force_augmentation=False):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.force_fraction(voice)
... rmakers.beam(voice)
... if force_augmentation is True:
... rmakers.force_augmentation(voice)
... score = lilypond_file["Score"]
... abjad.override(score).TupletBracket.bracket_visibility = True
... abjad.override(score).TupletBracket.staff_padding = 4.5
... abjad.setting(score).tupletFullLength = True
... return lilypond_file
.. container:: example
Without forced augmentation:
>>> pairs = [(2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs, force_augmentation=False)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 2/3
{
\time 2/8
c'8
[
c'8
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/3
{
c'8
[
c'8
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/3
{
c'8
[
c'8
c'8
]
}
}
}
}
.. container:: example
With forced augmentation:
>>> pairs = [(2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs, force_augmentation=True)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 4/3
{
\time 2/8
c'16
[
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/3
{
c'16
[
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/3
{
c'16
[
c'16
c'16
]
}
}
}
}
"""
for tuplet in abjad.select.tuplets(argument):
if not tuplet.augmentation():
tuplet.toggle_prolation()
[docs]def force_diminution(argument) -> None:
r"""
Spells tuplets in ``argument`` as diminutions.
.. container:: example
>>> def make_lilypond_file(pairs, force_diminution=False):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1], 16, extra_counts=[0, -1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.force_fraction(voice)
... rmakers.beam(voice)
... rmakers.swap_trivial(voice)
... if force_diminution is True:
... rmakers.force_diminution(voice)
... score = lilypond_file["Score"]
... abjad.override(score).TupletBracket.bracket_visibility = True
... abjad.override(score).TupletBracket.staff_padding = 4.5
... abjad.setting(score).tupletFullLength = True
... return lilypond_file
.. container:: example
Without forced diminution (default):
>>> pairs = [(1, 4), (1, 4), (1, 4), (1, 4)]
>>> lilypond_file = make_lilypond_file(pairs, force_diminution=False)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
{
\time 1/4
c'16
[
c'16
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/3
{
c'16
[
c'16
c'16
]
}
{
c'16
[
c'16
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 4/3
{
c'16
[
c'16
c'16
]
}
}
}
}
.. container:: example
With forced diminution (default):
>>> pairs = [(1, 4), (1, 4), (1, 4), (1, 4)]
>>> lilypond_file = make_lilypond_file(pairs, force_diminution=True)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
\with
{
\override TupletBracket.bracket-visibility = ##t
\override TupletBracket.staff-padding = 4.5
tupletFullLength = ##t
}
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
{
\time 1/4
c'16
[
c'16
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/3
{
c'8
[
c'8
c'8
]
}
{
c'16
[
c'16
c'16
c'16
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/3
{
c'8
[
c'8
c'8
]
}
}
}
}
"""
for tuplet in abjad.select.tuplets(argument):
if not tuplet.diminution():
tuplet.toggle_prolation()
[docs]def force_fraction(argument) -> None:
"""
Sets ``force_fraction=True`` on tuplets in ``argument``.
"""
for tuplet in abjad.select.tuplets(argument):
tuplet.force_fraction = True
[docs]def force_note(argument, *, tag: abjad.Tag | None = None) -> None:
r"""
Replaces leaves in ``argument`` with notes.
Changes logical ties 1 and 2 to notes:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... nested_music = rmakers.note(durations)
... components = abjad.sequence.flatten(nested_music)
... container = abjad.Container(components)
... rmakers.force_rest(components)
... logical_ties = abjad.select.logical_ties(container)[1:3]
... rmakers.force_note(logical_ties)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(7, 16), (3, 8), (7, 16), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 7/16
r4..
\time 3/8
c'4.
\time 7/16
c'4..
\time 3/8
r4.
}
}
}
.. container:: example
Changes leaves to notes with inverted composite pattern:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... nested_music = rmakers.note(durations)
... components = abjad.sequence.flatten(nested_music)
... container = abjad.Container(components)
... leaves = abjad.select.leaves(container)
... rmakers.force_rest(leaves)
... logical_ties = abjad.select.logical_ties(container)
... leaves = abjad.select.get(logical_ties, [0, -1])
... rmakers.force_note(leaves)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(7, 16), (3, 8), (7, 16), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 7/16
c'4..
\time 3/8
r4.
\time 7/16
r4..
\time 3/8
c'4.
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
leaves = abjad.select.leaves(argument)
for leaf in leaves:
if isinstance(leaf, abjad.Note):
continue
note = abjad.Note("C4", leaf.written_duration, tag=tag)
if leaf.multiplier is not None:
note.multiplier = leaf.multiplier
abjad.mutate.replace(leaf, [note])
[docs]def force_repeat_tie(
argument,
*,
tag: abjad.Tag | None = None,
threshold: bool | tuple[int, int] | typing.Callable = True,
) -> None:
r"""
Replaces ties in ``argument`` with repeat-ties.
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.tuplets(voice)[:-1]
... notes = [abjad.select.note(_, -1) for _ in tuplets]
... rmakers.tie(notes)
... rmakers.beam(voice)
... return lilypond_file
.. container:: example
Attaches tie to last note in each nonlast tuplet:
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
}
}
}
}
.. container:: example
Changes ties to repeat-ties:
>>> rmakers.force_repeat_tie(lilypond_file["Score"])
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
assert isinstance(argument, abjad.Container), repr(argument)
if callable(threshold):
inequality = threshold
elif threshold in (None, False):
def inequality(item):
return item < 0
elif threshold is True:
def inequality(item):
return item >= 0
else:
assert isinstance(threshold, tuple) and len(threshold) == 2, repr(threshold)
def inequality(item):
return item >= abjad.Duration(threshold)
attach_repeat_ties = []
for leaf in abjad.select.leaves(argument):
if abjad.get.has_indicator(leaf, abjad.Tie):
next_leaf = abjad.get.leaf(leaf, 1)
if next_leaf is None:
continue
if not isinstance(next_leaf, abjad.Chord | abjad.Note):
continue
if abjad.get.has_indicator(next_leaf, abjad.RepeatTie):
continue
duration = abjad.get.duration(leaf)
if not inequality(duration):
continue
attach_repeat_ties.append(next_leaf)
abjad.detach(abjad.Tie, leaf)
for leaf in attach_repeat_ties:
repeat_tie = abjad.RepeatTie()
abjad.attach(repeat_tie, leaf, tag=tag)
[docs]def force_rest(argument, *, tag: abjad.Tag | None = None) -> None:
r"""
Replaces leaves in ``argument`` with rests.
Forces first and last logical ties to rest:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... logical_ties = abjad.select.logical_ties(voice)
... logical_ties = abjad.select.get(logical_ties, [0, -1])
... rmakers.force_rest(logical_ties)
... rmakers.beam(voice)
... rmakers.attach_time_signatures(voice, time_signatures)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
r16
c'8
[
c'8.
]
\time 4/8
c'4
c'16
[
c'8
c'16
]
~
\time 3/8
c'8
c'4
\time 4/8
c'16
[
c'8
c'8.
]
r8
}
}
}
.. container:: example
Forces all logical ties to rest. Then sustains first and last logical ties:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... container = abjad.Container(tuplets)
... logical_ties = abjad.select.logical_ties(container)
... rmakers.force_rest(logical_ties)
... logical_ties = abjad.select.logical_ties(container)
... logical_ties = abjad.select.get(logical_ties, [0, -1])
... rmakers.force_note(logical_ties)
... rmakers.beam(container)
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
c'16
r8
r8.
\time 4/8
r4
r16
r8
r16
\time 3/8
r8
r4
\time 4/8
r16
r8
r8.
c'8
}
}
}
.. container:: example
Forces every other tuplet to rest:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.get(tuplets, [1], 2)
... rmakers.force_rest(tuplets)
... rmakers.beam(voice)
... rmakers.rewrite_rest_filled(voice)
... rmakers.extract_trivial(voice)
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
c'16
[
c'8
c'8.
]
\time 4/8
r2
\time 3/8
c'8
c'4
\time 4/8
r2
}
}
}
.. container:: example
Forces the first leaf and the last two leaves to rests:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... leaves = abjad.select.leaves(voice)
... leaves = abjad.select.get(leaves, [0, -2, -1])
... rmakers.force_rest(leaves)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
r16
c'8
[
c'8.
]
\time 4/8
c'4
c'16
[
c'8
c'16
]
~
\time 3/8
c'8
c'4
\time 4/8
c'16
[
c'8
]
r8.
r8
}
}
}
.. container:: example
Forces first leaf of every tuplet to rest:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... leaves = [abjad.select.leaf(_, 0) for _ in tuplets]
... rmakers.force_rest(leaves)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
r16
c'8
[
c'8.
]
\time 4/8
r4
c'16
[
c'8
c'16
]
\time 3/8
r8
c'4
\time 4/8
r16
c'8
[
c'8.
c'8
]
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
leaves = abjad.select.leaves(argument)
for leaf in leaves:
rest = abjad.Rest(leaf.written_duration, tag=tag)
if leaf.multiplier is not None:
rest.multiplier = leaf.multiplier
previous_leaf = abjad.get.leaf(leaf, -1)
next_leaf = abjad.get.leaf(leaf, 1)
abjad.mutate.replace(leaf, [rest])
if previous_leaf is not None:
abjad.detach(abjad.Tie, previous_leaf)
abjad.detach(abjad.Tie, rest)
abjad.detach(abjad.RepeatTie, rest)
if next_leaf is not None:
abjad.detach(abjad.RepeatTie, next_leaf)
[docs]def hide_skip_filled(argument) -> None:
"""
Hides skip-filled tuplets in ``argument``.
"""
tuplets = abjad.select.tuplets(argument)
for tuplet in tuplets:
if all(isinstance(_, abjad.Skip) for _ in tuplet):
tuplet.hide = True
[docs]def hide_trivial(argument) -> None:
r"""
Hides trivial tuplets in ``argument``.
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(voice)
... tuplets = abjad.select.tuplets(tuplets)[-2:]
... rmakers.hide_trivial(tuplets)
... return lilypond_file
>>> pairs = [(3, 8), (3, 8), (3, 8), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/3
{
\time 3/8
c'8
[
c'8
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 3/3
{
c'8
[
c'8
c'8
]
}
\scaleDurations #'(1 . 1)
{
c'8
[
c'8
c'8
]
}
\scaleDurations #'(1 . 1)
{
c'8
[
c'8
c'8
]
}
}
}
}
"""
tuplets = abjad.select.tuplets(argument)
for tuplet in tuplets:
if tuplet.trivial():
tuplet.hide = True
[docs]def invisible_music(argument, *, tag: abjad.Tag | None = None) -> None:
"""
Makes ``argument`` invisible.
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
tag_1 = tag.append(abjad.Tag("INVISIBLE_MUSIC_COMMAND"))
literal_1 = abjad.LilyPondLiteral(r"\abjad-invisible-music", site="before")
tag_2 = tag.append(abjad.Tag("INVISIBLE_MUSIC_COLORING"))
literal_2 = abjad.LilyPondLiteral(r"\abjad-invisible-music-coloring", site="before")
for leaf in abjad.select.leaves(argument):
abjad.attach(literal_1, leaf, tag=tag_1, deactivate=True)
abjad.attach(literal_2, leaf, tag=tag_2)
[docs]def interpolate(
start_duration: abjad.typings.Duration,
stop_duration: abjad.typings.Duration,
written_duration: abjad.typings.Duration,
) -> _classes.Interpolation:
"""
Makes interpolation.
"""
return _classes.Interpolation(
abjad.Duration(start_duration),
abjad.Duration(stop_duration),
abjad.Duration(written_duration),
)
[docs]def nongrace_leaves_in_each_tuplet(
argument, *, level: int = -1
) -> list[list[abjad.Leaf]]:
"""
Selects nongrace leaves in each tuplet.
"""
tuplets = abjad.select.tuplets(argument, level=level)
lists = [abjad.select.leaves(_, grace=False) for _ in tuplets]
for list_ in lists:
assert isinstance(list_, list)
assert all(isinstance(_, abjad.Leaf) for _ in list_), repr(list_)
return lists
[docs]def on_beat_grace_container(
voice: abjad.Voice,
voice_name: str,
nongrace_leaf_lists: typing.Sequence[typing.Sequence[abjad.Leaf]],
counts: typing.Sequence[int],
*,
grace_leaf_duration: abjad.typings.Duration | None = None,
grace_polyphony_command: abjad.VoiceNumber = abjad.VoiceNumber(1),
nongrace_polyphony_command: abjad.VoiceNumber = abjad.VoiceNumber(2),
tag: abjad.Tag | None = None,
talea: _classes.Talea = _classes.Talea([1], 8),
) -> None:
r"""
Makes on-beat grace containers.
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4], extra_counts=[2])
... voice = abjad.Voice(tuplets)
... tuplets = abjad.select.tuplets(voice)
... notes = [abjad.select.notes(_) for _ in tuplets]
... notes = [abjad.select.exclude(_, [0, -1]) for _ in notes]
... notes = abjad.select.notes(notes)
... groups = [[_] for _ in notes]
... rmakers.on_beat_grace_container(
... voice,
... "RhythmMaker.Music",
... groups,
... [2, 4],
... grace_leaf_duration=(1, 28)
... )
... components = abjad.mutate.eject_contents(voice)
... music_voice = abjad.Voice(components, name="RhythmMaker.Music")
... lilypond_file = rmakers.example(
... [music_voice], time_signatures, includes=["abjad.ily"]
... )
... staff = lilypond_file["Staff"]
... abjad.override(staff).TupletBracket.direction = abjad.UP
... abjad.override(staff).TupletBracket.staff_padding = 5
... return lilypond_file
>>> pairs = [(3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
\override TupletBracket.direction = #up
\override TupletBracket.staff-padding = 5
}
{
\context Voice = "Voice"
{
\context Voice = "RhythmMaker.Music"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/5
{
\time 3/4
c'4
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 10/21
[
(
c'8 * 10/21
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 10/21
[
(
c'8 * 10/21
c'8 * 10/21
c'8 * 10/21
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 10/21
[
(
c'8 * 10/21
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
}
>>
\oneVoice
c'4
}
}
}
}
}
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [5], 16)
... voice = abjad.Voice(tuplets)
... rmakers.extract_trivial(voice)
... logical_ties = abjad.select.logical_ties(voice)
... rmakers.on_beat_grace_container(
... voice,
... "RhythmMaker.Music",
... logical_ties,
... [6, 2],
... grace_leaf_duration=(1, 28)
... )
... components = abjad.mutate.eject_contents(voice)
... music_voice = abjad.Voice(components, name="RhythmMaker.Music")
... lilypond_file = rmakers.example(
... [music_voice], time_signatures, includes=["abjad.ily"]
... )
... return lilypond_file
>>> pairs = [(3, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\context Voice = "RhythmMaker.Music"
{
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 2/7
[
(
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
\time 3/4
c'4
~
c'16
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 2/7
[
(
c'8 * 2/7
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
~
c'16
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 2/7
[
(
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'8
~
c'8.
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 2/7
[
(
c'8 * 2/7
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
~
c'16
}
>>
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
c'
>8 * 2/7
[
(
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
c'8 * 2/7
)
]
}
\context Voice = "RhythmMaker.Music"
{
\voiceTwo
c'4
}
>>
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
assert isinstance(voice, abjad.Voice), repr(voice)
assert isinstance(voice_name, str), repr(voice_name)
assert isinstance(talea, _classes.Talea), repr(talea)
assert isinstance(grace_polyphony_command, abjad.VoiceNumber), repr(
grace_polyphony_command
)
assert isinstance(nongrace_polyphony_command, abjad.VoiceNumber), repr(
nongrace_polyphony_command
)
if voice_name:
voice.name = voice_name
cyclic_counts = abjad.CyclicTuple(counts)
start = 0
for i, nongrace_leaves in enumerate(nongrace_leaf_lists):
assert all(isinstance(_, abjad.Leaf) for _ in nongrace_leaves), repr(
nongrace_leaves
)
count = cyclic_counts[i]
if not count:
continue
stop = start + count
durations = talea[start:stop]
grace_leaves = abjad.makers.make_leaves([0], durations)
abjad.on_beat_grace_container(
grace_leaves,
nongrace_leaves,
grace_leaf_duration=grace_leaf_duration,
grace_polyphony_command=grace_polyphony_command,
nongrace_polyphony_command=nongrace_polyphony_command,
tag=tag,
)
[docs]def repeat_tie(argument, *, tag: abjad.Tag | None = None) -> None:
r"""
Attaches repeat-ties to leaves in ``argument``.
Attaches repeat-tie to first note in each nonfirst tuplet:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... voice = abjad.Voice(tuplets)
... tuplets = abjad.select.tuplets(voice)[1:]
... notes = [abjad.select.note(_, 0) for _ in tuplets]
... rmakers.repeat_tie(notes)
... rmakers.beam(voice)
... components = abjad.mutate.eject_contents(voice)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
}
}
}
}
.. container:: example
Attaches repeat-ties to nonfirst notes in each tuplet:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... voice = abjad.Voice(tuplets)
... tuplets = abjad.select.tuplets(voice)
... notes = [abjad.select.notes(_)[1:] for _ in tuplets]
... rmakers.repeat_tie(notes)
... rmakers.beam(voice)
... components = abjad.mutate.eject_contents(voice)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for note in abjad.select.notes(argument):
tie = abjad.RepeatTie()
abjad.attach(tie, note, tag=tag)
[docs]def reduce_multiplier(argument) -> None:
"""
Reduces multipliers of tuplets in ``argument``.
"""
for tuplet in abjad.select.tuplets(argument):
fraction = abjad.Fraction(*tuplet.multiplier)
pair = fraction.numerator, fraction.denominator
tuplet.multiplier = pair
[docs]def rewrite_dots(argument, *, tag: abjad.Tag | None = None) -> None:
"""
Rewrites dots of tuplets in ``argument``.
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for tuplet in abjad.select.tuplets(argument):
tuplet.rewrite_dots()
[docs]def rewrite_meter(
voice: abjad.Voice,
*,
boundary_depth: int | None = None,
reference_meters: typing.Sequence[abjad.Meter] = (),
tag: abjad.Tag | None = None,
) -> None:
r"""
Rewrites meter of components in ``voice``.
Use ``rmakers.wrap_in_time_signature_staff()`` to make sure ``voice``
appears together with time signature information in a staff.
Rewrites meter:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [5, 4], 16)
... voice = rmakers.wrap_in_time_signature_staff(
... tuplets, time_signatures)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... rmakers.rewrite_meter(voice)
... components = abjad.mutate.eject_contents(voice)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(3, 4), (3, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/4
c'4
~
c'16
[
c'8.
]
~
c'16
[
c'8.
]
~
c'8
[
c'8
]
~
c'8
[
c'8
]
~
c'8.
[
c'16
]
~
c'8.
[
c'16
]
~
c'4
c'4
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
assert isinstance(voice, abjad.Container), repr(voice)
staff = abjad.get.parentage(voice).parent
assert isinstance(staff, abjad.Staff), repr(staff)
time_signature_voice = staff["TimeSignatureVoice"]
assert isinstance(time_signature_voice, abjad.Voice)
meters, preferred_meters = [], []
for skip in time_signature_voice:
time_signature = abjad.get.indicator(skip, abjad.TimeSignature)
meter = abjad.Meter(time_signature)
meters.append(meter)
durations = [abjad.Duration(_) for _ in meters]
reference_meters = reference_meters or ()
split_measures(voice, durations=durations)
lists = abjad.select.group_by_measure(voice[:])
assert all(isinstance(_, list) for _ in lists), repr(lists)
for meter, list_ in zip(meters, lists):
for reference_meter in reference_meters:
if reference_meter == meter:
meter = reference_meter
break
preferred_meters.append(meter)
nontupletted_leaves = []
for leaf in abjad.iterate.leaves(list_):
if not abjad.get.parentage(leaf).count(abjad.Tuplet):
nontupletted_leaves.append(leaf)
unbeam(nontupletted_leaves)
abjad.Meter.rewrite_meter(
list_,
meter,
boundary_depth=boundary_depth,
rewrite_tuplets=False,
)
lists = abjad.select.group_by_measure(voice[:])
for meter, list_ in zip(preferred_meters, lists):
leaves = abjad.select.leaves(list_, grace=False)
beat_durations = []
beat_offsets = meter.depthwise_offset_inventory[1]
for start, stop in abjad.sequence.nwise(beat_offsets):
beat_duration = stop - start
beat_durations.append(beat_duration)
beamable_groups = _make_beamable_groups(leaves, beat_durations)
for beamable_group in beamable_groups:
if not beamable_group:
continue
abjad.beam(
beamable_group,
beam_rests=False,
tag=tag,
)
[docs]def rewrite_rest_filled(
argument, *, spelling=None, tag: abjad.Tag | None = None
) -> None:
r"""
Rewrites rest-filled tuplets in ``argument``.
Does not rewrite rest-filled tuplets:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [-1], 16, extra_counts=[1])
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (5, 16), (5, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 4/5
{
\time 4/16
r16
r16
r16
r16
r16
}
\times 4/5
{
r16
r16
r16
r16
r16
}
\tweak text #tuplet-number::calc-fraction-text
\times 5/6
{
\time 5/16
r16
r16
r16
r16
r16
r16
}
\tweak text #tuplet-number::calc-fraction-text
\times 5/6
{
r16
r16
r16
r16
r16
r16
}
}
}
}
Rewrites rest-filled tuplets:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [-1], 16, extra_counts=[1])
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)
... rmakers.rewrite_rest_filled(container)
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (5, 16), (5, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/16
r4
r4
\time 5/16
r4
r16
r4
r16
}
}
}
With spelling specifier:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [-1], 16, extra_counts=[1])
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)
... rmakers.rewrite_rest_filled(
... container,
... spelling=rmakers.Spelling(increase_monotonic=True)
... )
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (5, 16), (5, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/16
r4
r4
\time 5/16
r16
r4
r16
r4
}
}
}
.. container:: example
Working with ``rewrite_rest_filled``.
Makes rest-filled tuplets:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, -6, -6], 16, extra_counts=[1, 0]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 6/7
{
\time 3/8
c'8.
[
c'8.
]
r16
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
r4
r16
r8.
}
\tweak text #tuplet-number::calc-fraction-text
\times 6/7
{
\time 3/8
r8.
c'8.
[
c'16
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'8
r4.
}
}
}
}
Rewrites rest-filled tuplets:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, -6, -6], 16, extra_counts=[1, 0]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(voice)
... rmakers.rewrite_rest_filled(voice)
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 6/7
{
\time 3/8
c'8.
[
c'8.
]
r16
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
r2
}
\tweak text #tuplet-number::calc-fraction-text
\times 6/7
{
\time 3/8
r8.
c'8.
[
c'16
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'8
r4.
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
if spelling is not None:
increase_monotonic = spelling.increase_monotonic
forbidden_note_duration = spelling.forbidden_note_duration
forbidden_rest_duration = spelling.forbidden_rest_duration
else:
increase_monotonic = None
forbidden_note_duration = None
forbidden_rest_duration = None
for tuplet in abjad.select.tuplets(argument):
if not tuplet.rest_filled():
continue
duration = abjad.get.duration(tuplet)
rests = abjad.makers.make_leaves(
[None],
[duration],
increase_monotonic=increase_monotonic,
forbidden_note_duration=forbidden_note_duration,
forbidden_rest_duration=forbidden_rest_duration,
tag=tag,
)
abjad.mutate.replace(tuplet[:], rests)
tuplet.multiplier = (1, 1)
[docs]def rewrite_sustained(argument, *, tag: abjad.Tag | None = None) -> None:
r"""
Rewrites sustained tuplets in ``argument``.
Sustained tuplets generalize a class of rhythms composers are likely to rewrite:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [6, 5, 5, 4, 1], 16, extra_counts=[2, 1, 1, 1]
... )
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)[1:3]
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets]
... rmakers.tie(leaves)
... rmakers.beam(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (4, 16), (4, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 4/16
c'4.
}
\times 4/5
{
c'4
~
c'16
~
}
\times 4/5
{
c'4
~
c'16
~
}
\times 4/5
{
c'4
c'16
}
}
}
}
The first three tuplets in the example above qualify as sustained:
>>> staff = lilypond_file["Score"]
>>> for tuplet in abjad.select.tuplets(staff):
... abjad.get.sustained(tuplet)
...
True
True
True
False
Tuplets 0 and 1 each contain only a single **tuplet-initial** attack. Tuplet 2
contains no attack at all. All three fill their duration completely.
Tuplet 3 contains a **nonintial** attack that rearticulates the tuplet's duration
midway through the course of the figure. Tuplet 3 does not qualify as sustained.
.. container:: example
Rewrite sustained tuplets like this:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [6, 5, 5, 4, 1], 16, extra_counts=[2, 1, 1, 1]
... )
... container = abjad.Container(tuplets)
... tuplets = abjad.select.tuplets(container)[1:3]
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets]
... rmakers.tie(leaves)
... rmakers.rewrite_sustained(container)
... rmakers.beam(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (4, 16), (4, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/16
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
c'4
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
c'4
~
}
\times 4/5
{
c'4
c'16
}
}
}
}
.. container:: example
Rewrite sustained tuplets -- and then extract the trivial tuplets that result --
like this:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [6, 5, 5, 4, 1], 16, extra_counts=[2, 1, 1, 1]
... )
... container = abjad.Container(tuplets)
... rmakers.beam(container)
... tuplets = abjad.select.tuplets(container)[1:3]
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets]
... rmakers.tie(leaves)
... rmakers.rewrite_sustained(container)
... rmakers.extract_trivial(container)
... components = abjad.mutate.eject_contents(container)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(4, 16), (4, 16), (4, 16), (4, 16)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/16
c'4
c'4
~
c'4
~
\times 4/5
{
c'4
c'16
}
}
}
}
.. container:: example
With selector:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_)[:-1] for _ in tuplets]
... rmakers.tie(notes)
... rmakers.rewrite_sustained(tuplets[-2:])
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/2
{
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 2/2
{
c'4
}
}
}
}
.. container:: example
Sustains every other tuplet:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [1, 2, 3, 4], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.get(tuplets, [1], 2)
... notes = [abjad.select.notes(_)[:-1] for _ in tuplets]
... rmakers.tie(notes)
... rmakers.rewrite_sustained(tuplets)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 3/8
c'16
[
c'8
c'8.
]
\time 4/8
c'2
~
\time 3/8
c'8
c'4
\time 4/8
c'2
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for tuplet in abjad.select.tuplets(argument):
if not abjad.get.sustained(tuplet):
continue
duration = abjad.get.duration(tuplet)
leaves = abjad.select.leaves(tuplet)
last_leaf = leaves[-1]
if abjad.get.has_indicator(last_leaf, abjad.Tie):
last_leaf_has_tie = True
else:
last_leaf_has_tie = False
for leaf in leaves[1:]:
tuplet.remove(leaf)
assert len(tuplet) == 1, repr(tuplet)
if not last_leaf_has_tie:
abjad.detach(abjad.Tie, tuplet[-1])
abjad.mutate._set_leaf_duration(tuplet[0], duration, tag=tag)
tuplet.multiplier = (1, 1)
[docs]def split_measures(voice, *, durations=None, tag: abjad.Tag | None = None) -> None:
r"""
Splits measures in ``voice``.
Uses ``durations`` when ``durations`` is not none.
Tries to find time signature information (from the staff that contains ``voice``)
when ``durations`` is none.
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
if not durations:
# TODO: implement abjad.get() method for measure durations
staff = abjad.get.parentage(voice).parent
assert isinstance(staff, abjad.Staff)
voice_ = staff["TimeSignatureVoice"]
assert isinstance(voice_, abjad.Voice)
durations = [abjad.get.duration(_) for _ in voice_]
total_duration = sum(durations)
music_duration = abjad.get.duration(voice)
if total_duration != music_duration:
message = f"Total duration of splits is {total_duration!s}"
message += f" but duration of music is {music_duration!s}:"
message += f"\ndurations: {durations}."
message += f"\nvoice: {voice[:]}."
raise Exception(message)
abjad.mutate.split(voice[:], durations=durations)
[docs]def swap_length_1(argument) -> None:
"""
Swaps length-1 tuplets in ``argument`` with containers.
"""
tuplets = abjad.select.tuplets(argument)
for tuplet in tuplets:
if len(tuplet) == 1:
container = abjad.Container()
abjad.mutate.swap(tuplet, container)
[docs]def swap_skip_filled(argument) -> None:
"""
Swaps skip-filled tuplets in ``argument`` with containers.
"""
tuplets = abjad.select.tuplets(argument)
for tuplet in tuplets:
if all(isinstance(_, abjad.Skip) for _ in tuplet):
container = abjad.Container()
abjad.mutate.swap(tuplet, container)
[docs]def swap_trivial(argument) -> None:
r"""
Swaps trivial tuplets in ``argument`` with containers.
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(voice)
... tuplets = abjad.select.tuplets(tuplets)[-2:]
... rmakers.swap_trivial(tuplets)
... return lilypond_file
>>> pairs = [(3, 8), (3, 8), (3, 8), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 3/3
{
\time 3/8
c'8
[
c'8
c'8
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 3/3
{
c'8
[
c'8
c'8
]
}
{
c'8
[
c'8
c'8
]
}
{
c'8
[
c'8
c'8
]
}
}
}
}
"""
tuplets = abjad.select.tuplets(argument)
for tuplet in tuplets:
if tuplet.trivial():
container = abjad.Container()
abjad.mutate.swap(tuplet, container)
[docs]def tie(argument, *, tag: abjad.Tag | None = None) -> None:
r"""
Attaches ties to notes in ``argument``.
Attaches tie to last note in each nonlast tuplet:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.tuplets(tuplets)[:-1]
... notes = [abjad.select.note(_, -1) for _ in tuplets]
... rmakers.tie(notes)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
c'8
]
}
}
}
}
.. container:: example
Ties the last leaf of nonlast tuplets:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [5, 3, 3, 3], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.tuplets(tuplets)[:-1]
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets]
... rmakers.tie(leaves)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(4, 8), (3, 8), (4, 8), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/8
c'4
~
c'16
[
c'8.
]
~
\time 3/8
c'8.
[
c'8.
]
~
\time 4/8
c'4
~
c'16
[
c'8.
]
~
\time 3/8
c'8.
[
c'8.
]
}
}
}
.. container:: example
Ties across every other tuplet:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [5, 3, 3, 3], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... tuplets = abjad.select.get(tuplets[:-1], [0], 2)
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets]
... rmakers.tie(leaves)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(4, 8), (3, 8), (4, 8), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/8
c'4
~
c'16
[
c'8.
]
~
\time 3/8
c'8.
[
c'8.
]
\time 4/8
c'4
~
c'16
[
c'8.
]
~
\time 3/8
c'8.
[
c'8.
]
}
}
}
.. container:: example
TIE-CONSECUTIVE-NOTES RECIPE:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(durations, [5, -3, 3, 3], 16)
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.untie(voice)
... runs = abjad.select.runs(voice)
... notes = [abjad.select.notes(_)[:-1] for _ in runs]
... rmakers.tie(notes)
... rmakers.beam(voice)
... rmakers.extract_trivial(voice)
... return lilypond_file
>>> pairs = [(4, 8), (3, 8), (4, 8), (3, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\time 4/8
c'4
~
c'16
r8.
\time 3/8
c'8.
[
~
c'8.
]
~
\time 4/8
c'4
~
c'16
r8.
\time 3/8
c'8.
[
~
c'8.
]
}
}
}
.. container:: example
Attaches ties to nonlast notes in each tuplet:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_)[:-1] for _ in tuplets]
... rmakers.untie(notes)
... rmakers.tie(notes)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for note in abjad.select.notes(argument):
tie = abjad.Tie()
abjad.attach(tie, note, tag=tag)
[docs]def time_signatures(pairs: list[tuple[int, int]]) -> list[abjad.TimeSignature]:
"""
Makes time signatures from ``pairs``.
Documentation helper.
"""
assert all(isinstance(_, tuple) for _ in pairs), repr(pairs)
return [abjad.TimeSignature(_) for _ in pairs]
[docs]def tremolo_container(argument, count: int, *, tag: abjad.Tag | None = None) -> None:
r"""
Replaces notes in ``argument`` with tremolo containers.
Repeats figures two times each:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... groups = [abjad.select.get(_, [0, -1]) for _ in notes]
... rmakers.tremolo_container(groups, 2)
... rmakers.extract_trivial(voice)
... containers = abjad.select.components(voice, abjad.TremoloContainer)
... result = [abjad.slur(_) for _ in containers]
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(4, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\repeat tremolo 2 {
\time 4/4
c'16
(
c'16
)
}
c'4
c'4
\repeat tremolo 2 {
c'16
(
c'16
)
}
\repeat tremolo 2 {
\time 3/4
c'16
(
c'16
)
}
c'4
\repeat tremolo 2 {
c'16
(
c'16
)
}
}
}
}
Repeats figures four times each:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [4])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = [abjad.select.notes(_) for _ in tuplets]
... groups = [abjad.select.get(_, [0, -1]) for _ in notes]
... rmakers.tremolo_container(groups, 4)
... rmakers.extract_trivial(voice)
... containers = abjad.select.components(voice, abjad.TremoloContainer)
... result = [abjad.slur(_) for _ in containers]
... rmakers.attach_time_signatures(voice, time_signatures)
... return lilypond_file
>>> pairs = [(4, 4), (3, 4)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\repeat tremolo 4 {
\time 4/4
c'32
(
c'32
)
}
c'4
c'4
\repeat tremolo 4 {
c'32
(
c'32
)
}
\repeat tremolo 4 {
\time 3/4
c'32
(
c'32
)
}
c'4
\repeat tremolo 4 {
c'32
(
c'32
)
}
}
}
}
"""
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
for note in abjad.select.notes(argument):
container_duration = note.written_duration
note_duration = container_duration / (2 * count)
left_note = abjad.Note("c'", note_duration)
right_note = abjad.Note("c'", note_duration)
container = abjad.TremoloContainer(count, [left_note, right_note], tag=tag)
abjad.mutate.replace(note, container)
[docs]def trivialize(argument) -> None:
r"""
Trivializes tuplets in ``argument``.
Leaves trivializable tuplets as-is when no tuplet command is given. The tuplets
in measures 2 and 4 can be written as trivial tuplets, but they are not:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, 6, 6], 16, extra_counts=[0, 4]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
}
\times 2/3
{
\time 4/8
c'4.
c'4.
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
}
\times 2/3
{
\time 4/8
c'4.
c'4.
}
}
}
}
Rewrites trivializable tuplets as trivial (1:1) tuplets when ``trivialize`` is
true:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, 6, 6], 16, extra_counts=[0, 4]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.trivialize(voice)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
c'4
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
c'4
}
}
}
}
REGRESSION #907a. Rewrites trivializable tuplets even when tuplets contain
multiple ties:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, 6, 6], 16, extra_counts=[0, 4]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.trivialize(voice)
... leaves = [abjad.select.leaf(_, -1) for _ in tuplets[:-1]]
... rmakers.tie(leaves)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
c'4
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
c'8.
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
c'4
}
}
}
}
REGRESSION #907b. Rewrites trivializable tuplets even when tuplets contain very
long ties:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.talea(
... durations, [3, 3, 6, 6], 16, extra_counts=[0, 4]
... )
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... rmakers.trivialize(voice)
... notes = abjad.select.notes(voice)[:-1]
... rmakers.tie(notes)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(3, 8), (4, 8), (3, 8), (4, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
~
c'8.
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
~
c'4
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 3/8
c'8.
[
~
c'8.
]
~
}
\tweak text #tuplet-number::calc-fraction-text
\times 1/1
{
\time 4/8
c'4
~
c'4
}
}
}
}
"""
for tuplet in abjad.select.tuplets(argument):
tuplet.trivialize()
[docs]def unbeam(argument, *, smart: bool = False, tag: abjad.Tag | None = None) -> None:
r"""
Unbeams leaves in ``argument``.
Adjusts adjacent start- and stop-beams when ``smart=True``.
Unbeams 1 note:
.. container:: example
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[0], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
[
e'8
f'8
g'8
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[1], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
e'8
[
f'8
g'8
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[2], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
]
e'8
f'8
[
g'8
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[3], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
e'8
]
f'8
g'8
[
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[4], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
e'8
f'8
]
g'8
a'8
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[5], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
e'8
f'8
g'8
]
a'8
}
}
>>
.. container:: example
Unbeams 2 notes:
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[:2], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
e'8
[
f'8
g'8
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[1:3], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
e'8
f'8
[
g'8
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[2:4], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
]
e'8
f'8
g'8
[
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[3:5], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
e'8
]
f'8
g'8
a'8
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' e' f' g' a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[4:], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
[
d'8
e'8
f'8
]
g'8
a'8
}
}
>>
.. container:: example
Unbeams 1 note:
>>> voice = abjad.Voice("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[0], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
e'8
[
f'8
]
g'8
[
a'8
]
}
}
>>
>>> voice = abjad.Voice("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> staff = abjad.Staff([voice])
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(voice[1], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
\new Voice
{
c'8
d'8
e'8
[
f'8
]
g'8
[
a'8
]
}
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[2], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
f'8
g'8
[
a'8
]
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[3], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
f'8
g'8
[
a'8
]
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[4], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
[
f'8
]
g'8
a'8
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[5], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
[
f'8
]
g'8
a'8
}
>>
.. container:: example
Unbeams 2 notes:
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[:2], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
d'8
e'8
[
f'8
]
g'8
[
a'8
]
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[1:3], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
d'8
e'8
f'8
g'8
[
a'8
]
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[2:4], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
f'8
g'8
[
a'8
]
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[3:5], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
f'8
g'8
a'8
}
>>
>>> staff = abjad.Staff("c'8 [ d' ] e' [ f' ] g' [ a' ]")
>>> score = abjad.Score([staff])
>>> abjad.setting(score).autoBeaming = False
>>> rmakers.unbeam(staff[4:], smart=True)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
\with
{
autoBeaming = ##f
}
<<
\new Staff
{
c'8
[
d'8
]
e'8
[
f'8
]
g'8
a'8
}
>>
"""
leaves = abjad.select.leaves(argument)
leaf: abjad.Leaf | None
for leaf in leaves:
abjad.detach(abjad.BeamCount, leaf)
abjad.detach(abjad.StartBeam, leaf)
abjad.detach(abjad.StopBeam, leaf)
if smart is True:
tag = tag or abjad.Tag()
tag = tag.append(_function_name(inspect.currentframe()))
unmatched_start_beam = False
leaf = leaves[0]
leaf = abjad.get.leaf(leaf, -1)
if leaf is not None:
if abjad.get.has_indicator(leaf, abjad.StopBeam):
pass
elif abjad.get.has_indicator(leaf, abjad.StartBeam):
abjad.detach(abjad.StartBeam, leaf)
else:
while True:
leaf = abjad.get.leaf(leaf, -1)
if leaf is None:
break
if abjad.get.has_indicator(leaf, abjad.StopBeam):
break
if abjad.get.has_indicator(leaf, abjad.StartBeam):
unmatched_start_beam = True
break
unmatched_stop_beam = False
leaf = leaves[-1]
leaf = abjad.get.leaf(leaf, 1)
if leaf is not None:
if abjad.get.has_indicator(leaf, abjad.StartBeam):
pass
elif abjad.get.has_indicator(leaf, abjad.StopBeam):
abjad.detach(abjad.StopBeam, leaf)
else:
while True:
leaf = abjad.get.leaf(leaf, 1)
if leaf is None:
break
if abjad.get.has_indicator(leaf, abjad.StartBeam):
break
if abjad.get.has_indicator(leaf, abjad.StopBeam):
unmatched_stop_beam = True
break
if unmatched_start_beam is True:
leaf = leaves[0]
leaf = abjad.get.leaf(leaf, -1)
abjad.attach(abjad.StopBeam(), leaf, tag=tag)
if unmatched_stop_beam is True:
leaf = leaves[-1]
leaf = abjad.get.leaf(leaf, 1)
abjad.attach(abjad.StartBeam(), leaf, tag=tag)
[docs]def untie(argument) -> None:
r"""
Unties leaves in ``argument``.
Attaches ties to nonlast notes; then detaches ties from select notes:
.. container:: example
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... lilypond_file = rmakers.example(tuplets, time_signatures)
... voice = lilypond_file["Voice"]
... notes = abjad.select.notes(voice)[:-1]
... rmakers.tie(notes)
... notes = abjad.select.notes(voice)
... notes = abjad.select.get(notes, [0], 4)
... rmakers.untie(notes)
... rmakers.beam(voice)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
~
c'8
]
~
}
\times 2/3
{
c'8
[
~
c'8
c'8
]
~
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
}
\times 2/3
{
c'8
[
~
c'8
~
c'8
]
~
}
\times 2/3
{
c'8
[
c'8
~
c'8
]
~
}
\times 2/3
{
c'8
[
~
c'8
c'8
]
}
}
}
}
.. container:: example
Attaches repeat-ties to nonfirst notes; then detaches ties from select notes:
>>> def make_lilypond_file(pairs):
... time_signatures = rmakers.time_signatures(pairs)
... durations = [abjad.Duration(_) for _ in time_signatures]
... tuplets = rmakers.even_division(durations, [8], extra_counts=[1])
... voice = abjad.Voice(tuplets)
... notes = abjad.select.notes(voice)[1:]
... rmakers.repeat_tie(notes)
... notes = abjad.select.notes(voice)
... notes = abjad.select.get(notes, [0], 4)
... rmakers.untie(notes)
... rmakers.beam(voice)
... components = abjad.mutate.eject_contents(voice)
... lilypond_file = rmakers.example(components, time_signatures)
... return lilypond_file
>>> pairs = [(2, 8), (2, 8), (2, 8), (2, 8), (2, 8), (2, 8)]
>>> lilypond_file = make_lilypond_file(pairs)
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> score = lilypond_file["Score"]
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
{
\context RhythmicStaff = "Staff"
\with
{
\override Clef.stencil = ##f
}
{
\context Voice = "Voice"
{
\times 2/3
{
\time 2/8
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
\repeatTie
c'8
\repeatTie
c'8
]
}
\times 2/3
{
c'8
[
\repeatTie
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
c'8
\repeatTie
c'8
]
\repeatTie
}
\times 2/3
{
c'8
[
\repeatTie
c'8
c'8
]
\repeatTie
}
}
}
}
"""
for leaf in abjad.select.leaves(argument):
abjad.detach(abjad.Tie, leaf)
abjad.detach(abjad.RepeatTie, leaf)
[docs]def wrap_in_time_signature_staff(
components, time_signatures: list[abjad.TimeSignature]
) -> abjad.Voice:
"""
Wraps ``components`` in two-voice staff.
One voice for ``components`` and another voice for ``time_signatures``.
See ``rmakers.rewrite_meter()`` for examples of this function.
"""
assert all(isinstance(_, abjad.Component) for _ in components), repr(components)
assert all(isinstance(_, abjad.TimeSignature) for _ in time_signatures), repr(
time_signatures
)
score = _make_time_signature_staff(time_signatures)
music_voice = score["RhythmMaker.Music"]
music_voice.extend(components)
_validate_tuplets(music_voice)
return music_voice
[docs]def written_duration(argument, duration: abjad.typings.Duration) -> None:
"""
Sets written duration of leaves in ``argument``.
"""
duration_ = abjad.Duration(duration)
leaves = abjad.select.leaves(argument)
for leaf in leaves:
old_duration = leaf.written_duration
if duration_ == old_duration:
continue
leaf.written_duration = duration_
multiplier = old_duration / duration_
pair = abjad.duration.pair(multiplier)
leaf.multiplier = pair