Skip to content

gp2rs.py drops Guitar Pro arpeggio/handshape flag during import — chord templates never get arp #57

Description

@carochacs

Summary

lib/gp2rs.py (the binary Guitar Pro → arrangement-XML converter, used for GP3/GP4/GP5 import) never reads or propagates the arpeggio flag that Guitar Pro authors attach to a beat/chord. As a result, every GP-sourced chart imports its arpeggiated passages as ordinary strummed chords, and the downstream .feedpak handshape data (handshapes[].arp) is always false for GP imports — even when the source GP file explicitly marks the chord as an arpeggio.

This is not a request for a new wire-format concept — the arp field already exists and is spec-legal (see "Where this fits" below). It's a bug/gap in one converter: the flag exists in pyguitarpro's beat data, and there's a place downstream ready to receive it, but gp2rs.py never wires the two together.

Where this fits (already spec-legal, no FEP needed)

  • feedpak-spec/spec/feedpak-v1.md §6.5/§6.6 already define handshape.arp (boolean — "treat as an arpeggio span rather than a strummed hold") and chord-template arp.
  • feedback-plugin-feedpakr's feedpakr_handshapes.py (derive_handshapes()) already reads arp straight off the chord template the wire arrangement provides — i.e. the downstream consumer is correctly implemented and just waiting for the flag to actually be set.
  • The break is entirely upstream, in this repo.

What's happening in lib/gp2rs.py

  • ChordTemplate (around line 111) is defined as:

    @dataclass
    class ChordTemplate:
        name: str
        frets: list[int]   # per string, -1 = unused
        fingers: list[int] # per string, -1 = unused

    There is no arp/arpeggio field at all.

  • Chord templates are built and appended around line 1027 (chord_templates.append(ChordTemplate(name="", frets=list(frets), fingers=[-1] * width))) with no arpeggio detection anywhere in that code path.

  • gp2rs.py does already read other per-beat effect data off pyguitarpro's guitarpro.BeatEffect / guitarpro.NoteEffect objects in this same function — e.g.:

    • _gp_pick_direction() (line ~274) reads effect.stroke.direction / effect.pickStroke for strum direction, with detailed comments on which pyguitarpro field GP writes for authored chord strums vs. individual note picks.
    • getattr(eff, "letRing", False) (line ~911) is read and mapped to link_next.

    So the plumbing pattern for "read a pyguitarpro beat/note effect flag → set it on the wire model" is already established in this file; arpeggio just isn't one of the flags being read.

  • The only place in the codebase that currently sets arp/arpeggio on a chord template or handshape is the legacy arrangement-XML path (RS2014/EOF <handShape> elements with a displayName ending in -arp or an explicit arp attribute) — i.e. the loose-folder importer, not the binary GP parser. GP-authored arpeggio data specifically is what's being lost.

What needs to happen

  1. Identify the pyguitarpro field(s) that carry arpeggio/"let ring as arpeggio" semantics for a chord beat. (pyguitarpro exposes GP's BeatStroke with a "brush"/arpeggio-style stroke distinct from a simple down/up strum — worth checking guitarpro.BeatStrokeDirection and any arpeggio-specific enum/flag alongside it, and cross-checking against how EOF/RS2014 authoring tools decide when to emit arp="1" on a <handShape>, since that's the semantics we're trying to match.)
  2. Add an arp: bool = False field to ChordTemplate in gp2rs.py.
  3. In the chord-template construction/enrichment code (~line 1000-1045), set arp=True when the source GP beat carries that flag — following the existing "enrich from the GP chord diagram, only when it matches the actually-played voicing" guard pattern already used for name/fingers back-fill.
  4. Thread arp through to the arrangement XML output (wherever ChordTemplate fields are currently serialized — the fret/finger writing near the XML-emission code, mirroring how linkNext/pickDirection attrs are written per-note around line 1277/1316).
  5. Verify feedpakr_handshapes.py's derive_handshapes() picks it up correctly with no changes needed on the feedpakr side (per the earlier investigation, it already reads templates[cid].get('arp') — this should "just work" once gp2rs.py sets the flag).
  6. Add a regression test in tests/ (this repo uses pytest, tests/test_*.py, config in pyproject.toml) importing a small fixture GP file with a known authored arpeggio and asserting the resulting ChordTemplate.arp / arrangement-XML output.

Image

Context / mental model

For anyone unfamiliar with the RS/GP arpeggio convention: an arpeggio marker in Rocksmith-style notation is a "hold this chord shape" indicator, not an instruction to strike all strings at once. The shape shown establishes the fretting-hand handshape; only the individually highlighted notes crossing the strike line are actually picked at that moment, in sequence. Rocksmith 2014 arrangements generally represent this via the handshape mechanism (arp flag) rather than a dedicated arpeggio note-type — which is exactly the mechanism feedpak's handshape.arp already models. The gap here is purely that GP-sourced imports never populate it.

Repos involved (for reference, no action needed elsewhere)

  • get-flashbacks/feedpak-spec — format already supports this (§6.5/§6.6), no changes needed.
  • get-flashbacks/feedback-plugin-feedpakrfeedpakr_handshapes.py already correctly consumes arp from chord templates, no changes needed.
  • get-flashbacks/feedback (this repo) — lib/gp2rs.py is where the fix belongs.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions