remove_repeated_dynamics

auxjad.mutate.remove_repeated_dynamics(selection: abjad.select.Selection, *, ignore_hairpins: bool = False, reset_after_rests: bool = False, reset_after_duration: Optional[Union[float, int, str, tuple, abjad.duration.Duration]] = None)None[source]

Mutates an input abjad.Selection in place and has no return value; this function removes all consecutive repeated dynamic markings.

Basic usage:

When two consecutive leaves have identical dynamics, the second one is removed:

>>> staff = abjad.Staff(r"\time 3/8 c'4\pp d'8\pp | c'4\f d'8\f")
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-anw32e9i0f.png
>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-i5ylxkzv7md.png

Note

Auxjad automatically adds this function as an extension function to abjad.mutate. It can thus be used from either auxjad.mutate or abjad.mutate namespaces. Therefore, the two lines below are equivalent:

>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.mutate.remove_repeated_dynamics(staff[:])
Dynamic structure:

The function also removes dynamics that are separated by an arbitrary number of leaves without dynamics:

>>> staff = abjad.Staff(r"\time 3/8 c'4\p d'8 | e'4.\p | c'4\p d'8\f")
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-ha1x7s8d2fb.png
>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-g157jbbojhv.png
Subcontainers:

The container from which the selection is made can also have subcontainers:

>>> staff = abjad.Staff([abjad.Note("c'2"),
...                      abjad.Chord("<d' f'>2"),
...                      abjad.Tuplet((2, 3), "g2 a2 b2"),
...                      ])
>>> abjad.attach(abjad.Dynamic('ppp'), staff[0])
>>> abjad.attach(abjad.Dynamic('ppp'), staff[1])
>>> abjad.attach(abjad.Dynamic('ppp'), staff[2][0])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-4h9xze4780d.png
>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-7n9aaveoslu.png
ignore_hairpins:

By default, repeated dynamics with hairpins in between are not removed, but consecutive ones will.

>>> staff = abjad.Staff(r"c'2\p\< d'2\f\> | c'2\f d'2\f | e'1\p")
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-frmlobo3gis.png
>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-ov05k1imubj.png

To override the previous behaviour, set ignore_hairpins=True and hairpins will be ignored.

>>> staff = abjad.Staff(r"c'2\p\< d'2\f\> | c'2\f d'2\f | e'1\p")
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-2hdkt6cyca1.png
>>> auxjad.mutate.remove_repeated_dynamics(
...     staff[:],
...     ignore_hairpins=True,
... )
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-xkaipizr2jr.png
reset_after_rests:

By default, rests are treated just like any other leaf and thus notes with an identical dynamic separated by an arbitrary number of rests will be considered as repeated and the second dynamic will be removed.

>>> staff = abjad.Staff(r"c'4\pp r2. | c'1\pp")
>>> auxjad.mutate.remove_repeated_dynamics(staff[:])
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-wtno2t8qroh.png

To override the previous behaviour, set reset_after_rests to True and dynamics will always be restated after a rest.

>>> staff = abjad.Staff(r"c'4\pp r2. | c'1\pp")
>>> auxjad.mutate.remove_repeated_dynamics(
...     staff[:],
...     reset_after_rests=True,
... )
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-3e6g7u0q1i1.png
reset_after_duration:

With reset_after_rests is set to True, it is possible to specify a minimum duration of silence required for the dynamics to be restated using the argument reset_after_duration. It takes an abjad.Duration or also str, tuple, float, etc. This sets the maximum length of rests before which identical dynamics are restated. If the total length of rests falls below that value, then repeated dynamics are removed.

In the case below, a rest of r2. is shorter than a duration of (4, 4), so the repeated dynamic is removed.

>>> staff = abjad.Staff(r"c'4\pp r2. | c'1\pp")
>>> auxjad.mutate.remove_repeated_dynamics(
...     staff[:],
...     reset_after_rests=True,
...     reset_after_duration=(4, 4),
... )
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-b323xuesujc.png

But setting the duration to 2/4 forces the dynamic to be restated.

>>> staff = abjad.Staff(r"c'4\pp r2. | c'1\pp")
>>> auxjad.mutate.remove_repeated_dynamics(
...     staff[:],
...     reset_after_rests=True,
...     reset_after_duration=2 / 4,
... )
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-64dppx3cp99.png
reset_after_rests:

The function also handles measure rests with reset_after_rests.

>>> staff = abjad.Staff(r"c'4\pp r2. | c'4\pp r2. | R1 | c'1\pp")
>>> auxjad.mutate.remove_repeated_dynamics(
...     staff[:],
...     reset_after_rests=True,
...     reset_after_duration=abjad.Duration(4, 4),
... )
>>> abjad.show(staff)
../_images/remove_repeated_dynamics-jt7akhtbsge.png

Warning

The input selection must be a contiguous logical voice. When dealing with a container with multiple subcontainers (e.g. a score containing multiple staves), the best approach is to cycle through these subcontainers, applying this function to them individually.