The rhythm module¶
Classes and convenience functions to manipulate the rhythm of music.
For all convenience functions: the music argument may be a
parce.Document, a parce Cursor (optionally
only selecting a range of the document to edit), a node Range
or any Element node (DOM tree).
-
class
EditRhythm[source]¶ Bases:
quickly.dom.edit.EditBase class for rhythm editing operations.
-
static
may_remove(node)[source]¶ Return True if the duration of this node may be removed.
A duration may not be removed if
node.duration_requiredis True, or when the node’s right sibling has only the duration visible, such as is the case with an unpitched note or an empty lyric item.In that case, the current duration may not be removed, because the next duration would then be understood as the duration of the current node when rewriting the music text.
-
static
-
class
Remove[source]¶ Bases:
quickly.rhythm.EditRhythmRemove duration from Durable nodes, if allowed.
-
class
RemoveScaling[source]¶ Bases:
quickly.rhythm.EditRhythmRemove scaling from Durable nodes.
-
class
RemoveFractionScaling[source]¶ Bases:
quickly.rhythm.EditRhythmRemove scaling if it contains a fraction.
-
class
RhythmExplicit[source]¶ Bases:
quickly.rhythm.EditRhythmAdd the current duration to all nodes that don’t have one.
-
class
RhythmImplicit[source]¶ Bases:
quickly.rhythm.EditRhythmRemove reoccurring durations.
-
class
RhythmImplicitPerLine[source]¶ Bases:
quickly.rhythm.EditRhythmRemove reoccurring durations within the same line, but always add a duration to the first Durable on a line.
This only works when editing from a parce Document, otherwise we don’t know the newlines in the original text. If there is no parce Document, the behaviour is the same as
RhythmImplicit.
-
class
RhythmTransform(transform)[source]¶ Bases:
quickly.rhythm.EditRhythmTransform durations using a
Transform.This can be used for all types of shift and scale operations. For example, to add a dot to all durations:
>>> from quickly.rhythm import RhythmTransform >>> from quickly.duration import Transform >>> from quickly.dom import read >>> music = read.lily_document(r"{ c4 d8 e16 f g2 }") >>> t = Transform(dotcount=1) # add a dot >>> RhythmTransform(t).edit(music) >>> music.write() '{ c4. d8. e16. f g2. }'
Remove a dot:
>>> t = Transform(dotcount=-1) >>> RhythmTransform(t).edit(music) >>> music.write() '{ c4 d8 e16 f g2 }'
Double durations:
>>> t = Transform(log=-1) >>> RhythmTransform(t).edit(music) >>> music.write() '{ c2 d4 e8 f g1 }'
Add a scaling factor:
>>> t = Transform(scale=1/3) >>> RhythmTransform(t).edit(music) >>> music.write() '{ c2*1/3 d4*1/3 e8*1/3 f g1*1/3 }'
Or modify all in one go:
>>> t = Transform(1, 1, 3) >>> RhythmTransform(t).edit(music) >>> music.write() '{ c4. d8. e16. f g2. }'
This function also modifies durations in
\tempo,\tuplet,\afterand\partialcommands.
-
class
CopyRhythm(explicit=False)[source]¶ Bases:
quickly.rhythm.EditRhythmExtract durations from a range in the form of (duration, scaling) tuples.
The durations are returned by
edit_range()and thus also all other edit methods. Durables without duration yield a None ifexplicitis False, otherwise the previous duration is repeated. Example:>>> from quickly.dom import read >>> music = read.lily_document(r"{ c4 d8 e16 f g2 }") >>> from quickly.rhythm import CopyRhythm >>> durations = CopyRhythm().edit(music) >>> durations [(Fraction(1, 4), 1), (Fraction(1, 8), 1), (Fraction(1, 16), 1), None, (Fraction(1, 2), 1.0)] >>> CopyRhythm(True).edit(music) [(Fraction(1, 4), 1), (Fraction(1, 8), 1), (Fraction(1, 16), 1), (Fraction(1, 16), 1), (Fraction(1, 2), 1)]
-
readonly= True¶
-
explicit= None¶ If True, yield every reoccurring duration explicit instead of None
-
-
class
PasteRhythm(durations, cycle=True)[source]¶ Bases:
quickly.rhythm.EditRhythmPaste durations such as returned by
CopyRhythminto music.The durations are an iterable of either the two-tuple (duration, scaling) or None. If
cycleis True, the pasted durations are endlessly repeated in the selected range. Example:>>> from fractions import Fraction >>> durations = [(Fraction(1, 4), 1), (Fraction(3, 16), 0.5), None] >>> from quickly.dom import read >>> music = read.lily_document(r"{ c4 d8 e16 f g2 }") >>> from quickly.rhythm import PasteRhythm >>> PasteRhythm(durations).edit(music) >>> music.write() '{ c4 d8.*1/2 e f4 g8.*1/2 }'
-
remove(music)[source]¶ Remove all durations from music.
Does not remove the duration from
\skipand Unpitched notes, and also not from durables that immediately precede Unpitched notes (or empty lyric items), because the Unpitched’s duration would then be mistakenly held for the duration of the preceding note.
-
remove_fraction_scaling(music)[source]¶ Remove all scalings that contain a fraction (like
1/3) from the durations in music.
-
implicit(music, per_line=False)[source]¶ Remove all reoccuring durations from the music.
If
per_lineis True, the first duration in a text line is not removed, but rather added if absent. (This only works when editing a parce document or cursor, otherwise we can’t know the newlines in the original text.)An example:
>>> import parce >>> import quickly.rhythm >>> d=parce.Document(quickly.find('lilypond'), r'''music = { ... c4 d8 e8 f8 g8 a4 ... g f e4 d ... c d4 e2 ... } ... ''', transformer=True) >>> quickly.rhythm.implicit(d, True) >>> print(d.text()) music = { c4 d8 e f g a4 g4 f e d c4 d e2 }
-
transform(music, log=0, dotcount=0, scale=1)[source]¶ Transform durations in music by modifying log, dot count and/or scaling.
Increasing the log by 1 halves the durations, decreasing the log doubles them. (See also the
durationmodule.) An example, where the duration is halved and one dot is added:>>> from quickly.dom import read >>> from quickly import rhythm >>> m = read.lily_document("{ c4 d8 e16 f g2 }") >>> rhythm.transform(m, 1, 1) >>> m.write() '{ c8. d16. e32. f g4. }'
This function also modifies durations in
\tempo,\tuplet,\afterand\partialcommands.
-
copy(music, explicit=False)[source]¶ Extract durations from music.
Every duration is a two-tuple of integers or fractions (duration, scaling), or, if
explicitis False, None for Durables without duration. Ifexplicitis True, the previous duration is repeated for Durables without duration.
-
paste(music, durations, cycle=True)[source]¶ Replace durations in the music with the specified durations.
Every duration is a two-tuple of integers or fractions (duration, scaling), or None for Durables without duration. If
cycleis True, the pasted durations are endlessly repeated in the selected range. An example:>>> from quickly.dom import read >>> from quickly.rhythm import copy, paste >>> durs = copy(read.lily_document("{ 8. 16 8 }")) >>> durs [(Fraction(3, 16), 1.0), (Fraction(1, 16), 1.0), (Fraction(1, 8), 1.0)] >>> music = read.lily_document("{ g a g c d c a b a f g f }") >>> paste(music, durs) >>> music.write() '{ g8. a16 g8 c8. d16 c8 a8. b16 a8 f8. g16 f8 }'