Returns the extreme pitched note at each onset from a polyphonic score.
For each unique onset time, only the highest or lowest pitched note
is kept. All other notes at that onset are discarded.
Parameters:
-
score
(Score)
–
The polyphonic score to process.
-
method
(str, default:
'high'
)
–
Either "high" (which is the default) to keep the highest pitched note at each
onset, or "low" to keep the lowest.
Returns:
-
Score
–
A new, flattened score containing only the extreme pitched note
at each onset.
Source code in amads/polyphony/extreme.py
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 | def extreme(score: Score, method: str = "high") -> Score:
"""
Returns the extreme pitched note at each onset from a polyphonic score.
For each unique onset time, only the highest or lowest pitched note
is kept. All other notes at that onset are discarded.
Parameters
----------
score : Score
The polyphonic score to process.
method : str
Either "high" (which is the default) to keep the highest pitched note at each
onset, or "low" to keep the lowest.
Returns
-------
Score
A new, flattened score containing only the extreme pitched note
at each onset.
"""
method = method.lower()
# 1. Flatten the score
flat_score = score.flatten()
notes = flat_score.get_sorted_notes()
# 2. Group notes by onset and keep only the extreme pitch at each onset
onset_note: dict[float, Note] = {}
for note in notes:
onset = note.onset
if onset not in onset_note:
onset_note[onset] = note
else:
current = onset_note[onset]
if (
method == "high"
and note.pitch.midi_num > current.pitch.midi_num
):
onset_note[onset] = note
elif (
method == "low" and note.pitch.midi_num < current.pitch.midi_num
):
onset_note[onset] = note
# 3. Replace part content with only the extreme notes
part = flat_score.content[0]
part.content = sorted(onset_note.values(), key=lambda n: n.onset)
for note in part.content:
note.parent = part
return flat_score
|