Skip to content

Commit b79341b

Browse files
committed
gp3/gp4: extract note accent flags (0x02 heavy, 0x40 normal)
`GP3File.readNote` never read flag bits 0x02 (heavy accent) and 0x40 (normal accent) from the note flags byte, even though the docstring documented them. GP4 inherited this broken read path; only GP5 read them correctly. The writer side was asymmetric too: `GP3File.packNoteFlags` emitted 0x02 but not 0x40, while GP4 overrode it to add 0x40 only. Round-tripping a note with `accentuatedNote=True` through PGP silently dropped the flag. This change: * reads both flags in `GP3File.readNote` (inherited by GP4) * writes flag 0x40 in `GP3File.packNoteFlags` * drops the now-redundant override in `GP4File.packNoteFlags` * adds a round-trip regression test for all three formats Cross-checked against alphaTab's `Gp3To5Importer.ts:1203-1207` which extracts both flags universally. Closes #1
1 parent 43de65f commit b79341b

3 files changed

Lines changed: 35 additions & 2 deletions

File tree

src/guitarpro/gp3.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,9 @@ def readNote(self, note, guitarString, track):
899899
"""
900900
flags = self.readU8()
901901
note.string = guitarString.number
902+
note.effect.heavyAccentuatedNote = bool(flags & 0x02)
902903
note.effect.ghostNote = bool(flags & 0x04)
904+
note.effect.accentuatedNote = bool(flags & 0x40)
903905
if flags & 0x20:
904906
note.type = gp.NoteType(self.readU8())
905907
if flags & 0x01:
@@ -1443,6 +1445,8 @@ def packNoteFlags(self, note):
14431445
if note.velocity != gp.Velocities.default:
14441446
flags |= 0x10
14451447
flags |= 0x20
1448+
if note.effect.accentuatedNote:
1449+
flags |= 0x40
14461450
return flags
14471451

14481452
def writeNoteEffects(self, note):

src/guitarpro/gp4.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,6 @@ def writeNote(self, note):
655655

656656
def packNoteFlags(self, note):
657657
flags = super().packNoteFlags(note)
658-
if note.effect.accentuatedNote:
659-
flags |= 0x40
660658
if note.effect.isFingering:
661659
flags |= 0x80
662660
return flags

tests/test_conversion.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,37 @@ def testChord(tmpdir, caplog, filename):
126126
assert song == song2
127127

128128

129+
@pytest.mark.parametrize('filename', ['Effects.gp3', 'Effects.gp4', 'Effects.gp5'])
130+
def testNoteAccentuationRoundtrip(tmpdir, filename):
131+
"""Regression test for GP3/GP4 note accent flag extraction.
132+
133+
`GP3File.readNote` historically did not extract flag bits 0x02 (heavy
134+
accent) and 0x40 (normal accent), while `writeNote` *does* write them.
135+
GP4 inherits the broken read path; only GP5 read them correctly.
136+
137+
This caused a reader/writer asymmetry: accent flags were silently
138+
dropped on every parse, even though PGP could write them.
139+
"""
140+
filepath = LOCATION / filename
141+
song = gp.parse(filepath)
142+
note = song.tracks[0].measures[0].voices[0].beats[0].notes[0]
143+
144+
note.effect.accentuatedNote = True
145+
note.effect.heavyAccentuatedNote = True
146+
147+
destpath = str(tmpdir.join(filename))
148+
gp.write(song, destpath)
149+
song2 = gp.parse(destpath)
150+
note2 = song2.tracks[0].measures[0].voices[0].beats[0].notes[0]
151+
152+
assert note2.effect.accentuatedNote is True, (
153+
f'{filename}: accentuatedNote not preserved on round-trip'
154+
)
155+
assert note2.effect.heavyAccentuatedNote is True, (
156+
f'{filename}: heavyAccentuatedNote not preserved on round-trip'
157+
)
158+
159+
129160
@pytest.mark.parametrize('version', ['gp3', 'gp4', 'gp5'])
130161
def testReadErrorAnnotation(version):
131162
def writeToBytesIO(song):

0 commit comments

Comments
 (0)