Remove overlap
remove_overlap
¶
remove_overlap(
score: Score,
tolerance: float = 0.1,
min_separation: float = 0.0,
keep_ornaments: bool = True,
collapse_parts: bool = False,
) -> Score
Remove overlapping notes with the same pitch from a score.
Sometimes in piano parts, a note participates in two voices and is printed as if two voices play the same note in unison, when of course the pianist only plays the pitch once. After reading a musicXML score, these doubled notes will be represented in the score. You can use this function to remove overlap.
Other cases can arise from reductions or merging of parts, or from rounding errors. This function can be used to clean up these cases.
Caution: Grace notes read from musicXML files are often represented
as starting at the same time as the main note they ornament. By
default, this function will not remove ornaments, even if they have
the same pitch and onset as another note. Ornaments other than
grace notes are stored as properties of the note they are attached
to, but grace notes are independent notes with the 'is_grace'
property set to True. By default, grace notes and any ornamented
note cannot be merged with overlapping notes, but to allow this,
set keep_ornaments=False.
When producing MIDI output for playback, there is a risk of
rounding error causing a note-on to be placed immediately before
the note-off of a prceding note of the same pitch. This can cause
a "stuck note." A simple solution is to shorten notes by a small
amount when the same pitch follows immediately. Then, their note-off
event will be sorted before the next note's note-on event. (A
very slightly reduced duration is rarely audible, and separation
must be introduced in a physical piano performance.) The
min_separation parameter can be used to ensure that adjacent
notes with the same pitch are separated by at least that amount.
0.02 is a reasonable choice: no one can play 50 notes per beat,
but 0.02 is certain to quantize to at least one Standard MIDI File
tick at any reasonable tick size. If units are seconds, 0.02 is
just 20 milliseconds.
The score is first flattened (ties merged, notes extracted from
measures and staves). Within each part, notes sharing the same
key_num that overlap in time are resolved:
- If two notes start within
toleranceof each other, the note that starts first (or the first in sorted order when onsets are equal) is kept and extended to the maximum offset of the two; the second note is removed. - If the notes do not start within
tolerancebut the first note extends past the onset of the second, the first note is shortened so that it ends at the onset of the second note. The second note is extended to the offset of the first if necessary.
Each part is processed independently, so you must collapse parts
(e.g., left and right hand in piano parts) if you want to remove
overlap across parts. You can do this by passing collapse_parts=True
to this function, which is more efficient that collapsing parts before
calling this function.
Parameters:
-
score(Score) –The score to process. The original score is not modified; a new flat score is returned.
-
tolerance(float, default:0.1) –Maximum onset difference (in seconds or beats depending on the score's time unit) for two notes with the same
key_numto be considered simultaneous. Defaults to0.1. -
min_separation(float, default:0.0) –Minimum separation (in seconds or beats depending on the score's time unit) between adjacent notes with the same
key_num. If0.0, no minimum separation is enforced. Defaults to0.0. Must be less than half oftoleranceto avoid introducing note durations less than min_separation. -
keep_ornaments(bool, default:True) –If
True, notes withis_graceor other ornament properties (includinghas_trill) are not merged with other notes, even if they have the same pitch and onset as another note. Defaults toTrue. -
collapse_parts(bool, default:False) –If
True, all parts are merged into a single part before removing overlap. Defaults toFalse.
Returns:
-
Score–A new flat score with overlapping same-pitch notes resolved.
Examples:
Two notes with the same pitch that start at the same time are merged into a single note whose duration is the maximum of the two:
>>> from amads.core.basics import Note, Part, Score
>>> score = Score(Part(Note(pitch="C4", onset=0.0, duration=2.0),
... Note(pitch="C4", onset=0.0, duration=3.0)))
>>> result = remove_overlap(score)
>>> notes = result.content[0].content
>>> len(notes)
1
>>> notes[0].duration
3.0
A note that overlaps a later note with the same pitch is trimmed so that it ends exactly when the later note begins. The later note is extended if necessary to cover the full duration of the first note:
>>> score = Score(Part(Note(pitch="C4", onset=0.0, duration=4.0),
... Note(pitch="C4", onset=1.0, duration=2.0)))
>>> result = remove_overlap(score)
>>> notes = result.content[0].content
>>> len(notes)
2
>>> notes[0].duration
1.0
>>> notes[1].onset
1.0
>>> notes[1].duration
3.0
Use min_separation to ensure that adjacent notes with the same pitch are separated by at least that amount:
>>> score = Score(Part(Note(pitch="C4", onset=0.0, duration=4.0),
... Note(pitch="C4", onset=4.0, duration=2.0)))
>>> result = remove_overlap(score, min_separation=0.02)
>>> notes = result.content[0].content
>>> len(notes)
2
>>> notes[0].duration
3.98
>>> notes[1].onset
4.0
>>> notes[1].duration
2.0
Source code in amads/algorithms/remove_overlap.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |