mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-12 21:28:32 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d79e216b3 | ||
|
|
bd22951874 | ||
|
|
eb2121b4bc | ||
|
|
297778864c | ||
|
|
3ab57977c4 |
@@ -69,6 +69,7 @@ class RsNote:
|
|||||||
tremolo: bool = False
|
tremolo: bool = False
|
||||||
tap: bool = False
|
tap: bool = False
|
||||||
link_next: bool = False
|
link_next: bool = False
|
||||||
|
staff: int = -1 # Piano staff: -1=absent, 0=LH/bass clef, 1=RH/treble clef
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -1021,6 +1022,8 @@ def _build_xml(
|
|||||||
"tap": "1" if n.tap else "0",
|
"tap": "1" if n.tap else "0",
|
||||||
"ignore": "0",
|
"ignore": "0",
|
||||||
}
|
}
|
||||||
|
if getattr(n, 'staff', -1) != -1:
|
||||||
|
attrs["staff"] = str(n.staff)
|
||||||
ET.SubElement(notes_el, "note", **attrs)
|
ET.SubElement(notes_el, "note", **attrs)
|
||||||
|
|
||||||
# Chords
|
# Chords
|
||||||
|
|||||||
+20
-30
@@ -279,7 +279,6 @@ def _gpif_tracks(root: ET.Element) -> list[dict]:
|
|||||||
midi_channel = 0
|
midi_channel = 0
|
||||||
is_drums = False
|
is_drums = False
|
||||||
if gm is not None:
|
if gm is not None:
|
||||||
# GP6 (.gpx): <GeneralMidi table="Percussion"><Program>...</Program>
|
|
||||||
try: midi_program = int(gm.findtext('Program') or 0)
|
try: midi_program = int(gm.findtext('Program') or 0)
|
||||||
except (ValueError, TypeError): pass
|
except (ValueError, TypeError): pass
|
||||||
try:
|
try:
|
||||||
@@ -289,25 +288,6 @@ def _gpif_tracks(root: ET.Element) -> list[dict]:
|
|||||||
except (ValueError, TypeError): pass
|
except (ValueError, TypeError): pass
|
||||||
if gm.get('table') == 'Percussion':
|
if gm.get('table') == 'Percussion':
|
||||||
is_drums = True
|
is_drums = True
|
||||||
else:
|
|
||||||
# GP7/GP8 (.gp): <InstrumentSet><Type>drumKit</Type>
|
|
||||||
# and <MidiConnection><PrimaryChannel>9</PrimaryChannel>
|
|
||||||
inst_set = t.find('InstrumentSet')
|
|
||||||
if inst_set is not None:
|
|
||||||
inst_type = (inst_set.findtext('Type') or '').lower()
|
|
||||||
if inst_type == 'drumkit':
|
|
||||||
is_drums = True
|
|
||||||
midi_conn = t.find('MidiConnection')
|
|
||||||
if midi_conn is not None:
|
|
||||||
try:
|
|
||||||
ch_text = (midi_conn.findtext('PrimaryChannel') or '').strip()
|
|
||||||
if ch_text:
|
|
||||||
ch = int(ch_text)
|
|
||||||
midi_channel = ch
|
|
||||||
if ch == 9:
|
|
||||||
is_drums = True
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# String tuning
|
# String tuning
|
||||||
string_pitches: list[int] = []
|
string_pitches: list[int] = []
|
||||||
@@ -624,15 +604,14 @@ def list_tracks(gp_path: str) -> list[dict]:
|
|||||||
result = []
|
result = []
|
||||||
for i, t in enumerate(tracks):
|
for i, t in enumerate(tracks):
|
||||||
is_bass = bool(
|
is_bass = bool(
|
||||||
not t['is_drums'] # drums always have low/zero string pitches — must exclude
|
(
|
||||||
and (
|
not t['is_drums']
|
||||||
(
|
and not t['string_pitches'] # no string tuning = not guitar-family
|
||||||
not t['string_pitches'] # no string tuning = not guitar-family
|
and 32 <= t['midi_program'] <= 39
|
||||||
and 32 <= t['midi_program'] <= 39
|
) or (
|
||||||
) or (
|
not t['is_drums'] # explicit guard: drums can have low string pitches
|
||||||
t['string_pitches']
|
and t['string_pitches']
|
||||||
and max(t['string_pitches']) <= 48 # bass top string ≤ C3
|
and max(t['string_pitches']) <= 48 # bass top string ≤ C3
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
is_piano = (
|
is_piano = (
|
||||||
@@ -1339,7 +1318,7 @@ def convert_file(
|
|||||||
if bid != '-1' and bid:
|
if bid != '-1' and bid:
|
||||||
bar = bars_by_id.get(bid)
|
bar = bars_by_id.get(bid)
|
||||||
if bar is not None:
|
if bar is not None:
|
||||||
for vid in bar.findtext('Voices', '').split():
|
for voice_pos, vid in enumerate(bar.findtext('Voices', '').split()):
|
||||||
if vid == '-1':
|
if vid == '-1':
|
||||||
continue
|
continue
|
||||||
voice = voices_dict.get(vid)
|
voice = voices_dict.get(vid)
|
||||||
@@ -1440,6 +1419,13 @@ def convert_file(
|
|||||||
fret=rs_fret,
|
fret=rs_fret,
|
||||||
sustain=sustain,
|
sustain=sustain,
|
||||||
)
|
)
|
||||||
|
# Staff assignment for keys/piano (slopsmith staff schema).
|
||||||
|
# Derived from voice position as authored in the GP tab —
|
||||||
|
# not inferred from pitch — preserving hand crossings.
|
||||||
|
# Voice 0 = treble/RH staff (staff=1),
|
||||||
|
# Voice 1+ = bass/LH staff (staff=0).
|
||||||
|
if is_keys:
|
||||||
|
rn.staff = 1 if voice_pos == 0 else 0
|
||||||
|
|
||||||
# Techniques — GPIF stores these as <Property>
|
# Techniques — GPIF stores these as <Property>
|
||||||
# elements (NOT child tags), so the old
|
# elements (NOT child tags), so the old
|
||||||
@@ -1674,6 +1660,10 @@ def convert_file(
|
|||||||
fret=_lh_midi % 24,
|
fret=_lh_midi % 24,
|
||||||
sustain=_lh_dur if _lh_dur > 0.2 else 0.0,
|
sustain=_lh_dur if _lh_dur > 0.2 else 0.0,
|
||||||
)
|
)
|
||||||
|
# LH track notes are always bass clef (staff=0).
|
||||||
|
# The LH track as a whole IS the left hand —
|
||||||
|
# voice position within the LH track is irrelevant.
|
||||||
|
_lh_rn.staff = 0
|
||||||
_lh_notes.append(_lh_rn)
|
_lh_notes.append(_lh_rn)
|
||||||
_lh_last_per_key[_lh_midi] = _lh_rn
|
_lh_last_per_key[_lh_midi] = _lh_rn
|
||||||
_lh_vt += _lh_dur
|
_lh_vt += _lh_dur
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class Note:
|
|||||||
right_hand: int = -1
|
right_hand: int = -1
|
||||||
pick_direction: int = -1
|
pick_direction: int = -1
|
||||||
ignore: bool = False
|
ignore: bool = False
|
||||||
|
staff: int = -1 # Piano staff: -1=absent, 0=LH/bass clef, 1=RH/treble clef
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -217,6 +218,8 @@ def note_to_wire(n: Note) -> dict:
|
|||||||
out["pkd"] = n.pick_direction
|
out["pkd"] = n.pick_direction
|
||||||
if n.ignore:
|
if n.ignore:
|
||||||
out["ig"] = True
|
out["ig"] = True
|
||||||
|
if n.staff != -1:
|
||||||
|
out["stf"] = n.staff
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -307,6 +310,7 @@ def note_from_wire(d: dict, time: float | None = None) -> Note:
|
|||||||
right_hand=_wire_int_optional(d.get("rh"), -1),
|
right_hand=_wire_int_optional(d.get("rh"), -1),
|
||||||
pick_direction=_wire_int_optional(d.get("pkd"), -1),
|
pick_direction=_wire_int_optional(d.get("pkd"), -1),
|
||||||
ignore=bool(d.get("ig", False)),
|
ignore=bool(d.get("ig", False)),
|
||||||
|
staff=_wire_int_optional(d.get("stf"), -1),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -762,6 +766,7 @@ def _parse_note(n) -> Note:
|
|||||||
right_hand=_int_optional(n, "rightHand", -1),
|
right_hand=_int_optional(n, "rightHand", -1),
|
||||||
pick_direction=_int_optional(n, "pickDirection", -1),
|
pick_direction=_int_optional(n, "pickDirection", -1),
|
||||||
ignore=_bool(n, "ignore"),
|
ignore=_bool(n, "ignore"),
|
||||||
|
staff=_int_optional(n, "staff", -1),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user