mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-11 03:09:57 +00:00
fix: correctly import and notate multi-staff (piano/keys) tracks from GP8 (#692)
* fix: correctly import and notate multi-staff (piano/keys) tracks from GP8 Fixes bass stave being dropped on import (bar-column enumeration bug) and wrong hand-split heuristic in notation_lift for chords straddling middle C. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: byrongamatos <xasiklas@gmail.com> * fix(gp-import): fold all grand-staff staves, per-stave tuning, playable hand-splits Addresses review on #692 (topkoa): - split_hands: only use the middle-C boundary when both resulting hands are within HAND_SPLIT_SPAN_SEMITONES, else fall back to the largest-gap heuristic — a hard middle-C split otherwise put a 19-semitone (unplayable) span in one hand for bass-under-treble voicings (e.g. E2+B3 under an Em7 shape). - Treat any multi-stave (grand-staff) track as keys end-to-end, so the stave-0 and folded stave-1+ notes share one encoding and note_count (which sums every stave column) matches what actually imports — closing the phantom-count case for grand-staff instruments the name/program heuristics miss (harp, celesta, marimba). - Fold *every* extra stave (stave_columns[1:]), not just stave 1. - Per-staff tuning fall-back to the track-level Tuning property so an untuned staff never yields an empty pitch list (silent note loss); via a shared _parse_tuning helper. - Extract _collect_column_notes / _merge_lh_notes so the GPX LH/RH pair merge and the GP8 grand-staff fold share one implementation and can't drift in tie/timing/dedup handling. - Rebuild filtered_to_raw from the already-computed stave_columns (one source of truth for the counting rule) and drop the dead num_raw_tracks/raw_tracks. Tests: grand-staff fold + bar-column offset (test_gp2notation.py); both middle-C split cases (test_notation_lift.py). CHANGELOG updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: byrongamatos <xasiklas@gmail.com> --------- Signed-off-by: byrongamatos <xasiklas@gmail.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: byrongamatos <xasiklas@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
byrongamatos
parent
991eadeff6
commit
749af31cc3
@@ -85,6 +85,26 @@ def test_split_hands_narrow_group_goes_by_mean_vs_middle_c():
|
||||
assert "rh" in high and "lh" not in high # mean ~65.5 ≥ 60
|
||||
|
||||
|
||||
def test_split_hands_straddling_middle_c_splits_at_middle_c():
|
||||
# [G2, E3, C4] = [43, 52, 60]: largest gap is G2→E3 (9) but the musically
|
||||
# correct split is E3|C4. Middle-C boundary → lh=[G2,E3], rh=[C4].
|
||||
notes = [{"t": 0.0, "midi": m, "sus": 0} for m in (43, 52, 60)]
|
||||
hands = nl.split_hands(notes)
|
||||
assert sorted(n["midi"] for n in hands["lh"]) == [43, 52]
|
||||
assert [n["midi"] for n in hands["rh"]] == [60]
|
||||
|
||||
|
||||
def test_split_hands_middle_c_split_falls_back_when_it_makes_unplayable_hand():
|
||||
# Em7-shape RH voicing over a low bass note: [E2, B3, D4, G4] = [40,59,62,67].
|
||||
# A hard middle-C split would put E2+B3 in the LH — a 19-semitone span that
|
||||
# re-violates the 12-semitone threshold. Must fall back to the largest gap,
|
||||
# isolating E2 in the LH and keeping the treble voicing in the RH.
|
||||
notes = [{"t": 0.0, "midi": m, "sus": 0} for m in (40, 59, 62, 67)]
|
||||
hands = nl.split_hands(notes)
|
||||
assert [n["midi"] for n in hands["lh"]] == [40]
|
||||
assert sorted(n["midi"] for n in hands["rh"]) == [59, 62, 67]
|
||||
|
||||
|
||||
# ── Timing ───────────────────────────────────────────────────────────────────
|
||||
|
||||
def test_downbeat_times_filters_non_downbeats_and_sorts():
|
||||
|
||||
Reference in New Issue
Block a user