Skip to content

Commit

Permalink
Merge pull request #384 from leleogere/add_clef_map
Browse files Browse the repository at this point in the history
Add clef map
  • Loading branch information
sildater authored Oct 29, 2024
2 parents 65ec4c5 + b585213 commit faa6b52
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 1 deletion.
72 changes: 71 additions & 1 deletion partitura/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
object). This object serves as a timeline at which musical elements
are registered in terms of their start and end times.
"""

from collections.abc import Callable
from copy import copy, deepcopy
from collections import defaultdict
from collections.abc import Iterable
Expand Down Expand Up @@ -46,6 +46,7 @@
key_mode_to_int,
_OrderedSet,
update_note_ids_after_unfolding,
clef_sign_to_int,
)
from partitura.utils.generic import interp1d
from partitura.utils.music import transpose_note, step2pc
Expand Down Expand Up @@ -229,6 +230,75 @@ def key_signature_map(self):
fill_value="extrapolate",
)

@property
def clef_map(self) -> Callable[[int], np.ndarray]:
"""A function mapping timeline times to the clef in each
staff at that time. The function can take scalar
values or lists/arrays of values
Returns
-------
function
The mapping function
"""
clefs = np.array(
[
(
c.start.t,
c.staff,
clef_sign_to_int(c.sign),
c.line,
c.octave_change if c.octave_change is not None else 0
)
for c in self.iter_all(Clef)
]
)

interpolators = []
for s in range(1, self.number_of_staves + 1):
staff_clefs = clefs[clefs[:, 1] == s]
if len(staff_clefs) == 0:
# default treble clef
staff, clef, line, octave_change = s, clef_sign_to_int("G"), 2, 0

warnings.warn(
"No clefs found on staff {}, assuming {} clef.".format(s, clef)
)
if self.first_point is None:
t0, tN = 0, 0
else:
t0 = self.first_point.t
tN = self.last_point.t
staff_clefs = np.array(
[
(t0, staff, clef, line, octave_change),
(tN, staff, clef, line, octave_change),
]
)
elif len(staff_clefs) == 1:
# If there is only a single clef
staff_clefs = np.array([staff_clefs[0, :], staff_clefs[0, :]])
elif staff_clefs[0, 0] > self.first_point.t:
staff_clefs = np.vstack(
((self.first_point.t, *staff_clefs[0, 1:]), staff_clefs)
)

interpolators.append(
interp1d(
staff_clefs[:, 0],
staff_clefs[:, 1:],
axis=0,
kind="previous",
bounds_error=False,
fill_value="extrapolate",
)
)

def collator(time: int) -> np.ndarray:
return np.array([interpolator(time) for interpolator in interpolators], dtype=int)

return collator

@property
def measure_map(self):
"""A function mapping timeline times to the start and end of
Expand Down
4 changes: 4 additions & 0 deletions partitura/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
pianoroll_to_notearray,
match_note_arrays,
key_mode_to_int,
clef_sign_to_int,
clef_int_to_sign,
remove_silence_from_performed_part,
note_array_from_part_list,
slice_notearray_by_time,
Expand Down Expand Up @@ -74,6 +76,8 @@
"key_name_to_fifths_mode",
"fifths_mode_to_key_name",
"key_mode_to_int",
"clef_sign_to_int",
"clef_int_to_sign",
"pitch_spelling_to_midi_pitch",
"pitch_spelling_to_note_name",
"show_diff",
Expand Down
12 changes: 12 additions & 0 deletions partitura/utils/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,3 +729,15 @@
"vii": (7, "M"),
},
}

#["G", "F", "C", "percussion", "TAB", "jianpu", "none"]
CLEF_TO_INT = {
"G": 0,
"F": 1,
"C": 2,
"percussion": 3,
"TAB": 4,
"jianpu": 5,
"none": 6,
}
INT_TO_CLEF = {v: k for k, v in CLEF_TO_INT.items()}
6 changes: 6 additions & 0 deletions partitura/utils/music.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ def key_int_to_mode(mode):
raise ValueError("Unknown mode {}".format(mode))


def clef_sign_to_int(clef_sign: str) -> int:
return CLEF_TO_INT[clef_sign]

def clef_int_to_sign(clef_int: int) -> str:
return INT_TO_CLEF[clef_int]

def estimate_symbolic_duration(
dur, div, eps=10**-3, return_com_durations=False
) -> Union[Dict[str, Any], Tuple[Dict[str, Any]]]:
Expand Down
5 changes: 5 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@
for fn in ["test_ts_map_ts_starts_not_at_zero.xml"]
]

CLEF_MAP_TESTFILES = [
os.path.join(MUSICXML_PATH, fn)
for fn in ["test_clef_map.musicxml"]
]

REST_ARRAY_TESTFILES = [
os.path.join(MUSICXML_PATH, fn)
for fn in ["test_unfold_complex.xml", "test_rest.musicxml"]
Expand Down
Loading

0 comments on commit faa6b52

Please sign in to comment.