fix(gp2rs): write beat times at 6-decimal precision so imported tempo matches Guitar Pro (#819)

* fix(gp2rs): write beat times at 6-decimal precision

The editor/timeline derives per-bar BPM from beat spans
(bpm = beats*60/span), which amplifies rounding: at millisecond
(3-decimal) precision a constant-tempo GP import (e.g. 140 BPM) shows a
spurious per-bar "tempo drift" of ~0.05-0.7 BPM because most bar lengths
don't land on a ms boundary (worse for fast/odd meters). gp2rs computes
these beat times exactly from the GP tempo map, so the only precision
loss is the ebeat/startBeat format string. Writing them at 6 decimals
(microseconds) makes the derived tempo match GP's authored value.

Verified on GP5 imports (Highway to Hell 116, Equivalence 140, Living
After Midnight 138): the derived per-bar BPM collapses from two drifting
values to the single authored constant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013JgxKh99UAeQqmhzSc73tv
Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>

* test(gp2rs): compare ebeat times by value, not string

The 6-decimal beat-time write makes _assert_ebeats' exact-string compare fail
("0.500" vs "0.500000"). These tests only assert spacing, so parse both sides
to float — precision-agnostic, no need to rewrite every parametrized list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Signed-off-by: ChrisBeWithYou <christian.a.cowan@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Byron Gamatos <xasiklas@gmail.com>
This commit is contained in:
ChrisBeWithYou
2026-07-10 13:12:10 +02:00
committed by GitHub
co-authored by Claude Opus 4.8 Byron Gamatos
parent 751209b80e
commit f1bae9774c
2 changed files with 14 additions and 4 deletions
+4 -1
View File
@@ -121,7 +121,10 @@ def _converter_ebeats(converter, numerator, denominator, tempo_changes=None):
def _assert_ebeats(converter, numerator, denominator, expected_times, tempo_changes=None):
ebeats = _converter_ebeats(converter, numerator, denominator, tempo_changes)
assert [ebeat.get("time") for ebeat in ebeats] == expected_times
# Compare by value, not string: beat times are written at 6-decimal
# (microsecond) precision so the derived per-bar tempo matches the authored
# GP value, but these tests only care about the spacing, not the format.
assert [float(ebeat.get("time")) for ebeat in ebeats] == [float(t) for t in expected_times]
assert [ebeat.get("measure") for ebeat in ebeats] == [
"1",
*["-1"] * (len(expected_times) - 1),