FA-81526 / MIDI event timing / Open access
Bar, beat and tick position with meter changes: bar numbers restart after a meter change · case 01
After a change to 3/4 at bar 3, the first bar in the new meter is reported as bar 1 again.
ROOT CAUSE
The bar number is computed within the current signature segment without adding the segment's starting bar.
VERIFIED REPAIR
Restore the segment bar origin step so that it reads `b + offset // bar_len + 1`.
Unsuccessful approach: Adding the segment start but dropping the +1 reports zero-based bar numbers.
Case contract
Input [ppq, signatures, tick]. signatures is a list of [bar_index, numerator, denominator] sorted by bar, the first at bar 0; each takes effect at the start of its bar. A beat lasts ppq*4/denominator ticks. Return [bar (1-based), beat (1-based), tick within beat]; invalid input returns None.
Why this case matters
MIDI sequencers, file readers and synth drivers depend on exact event ordering and tick/time arithmetic.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
ppq, sigs, tick = x
if tick < 0 or not sigs or sigs[0][0] != 0:
return None
start = 0
for k, (b, num, den) in enumerate(sigs):
beat = ppq * 4 // den
bar_len = beat * num
next_bar = sigs[k + 1][0] if k + 1 < len(sigs) else None
if next_bar is not None:
span = (next_bar - b) * bar_len
if tick >= start + span:
start += span
continue
offset = tick - start
return [offset // bar_len + 1, offset % bar_len // beat + 1, offset % beat]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([480, [[0, 4, 4]], 0], [1, 1, 0]), ([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None)], [([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0])], [([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64])], [([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0])], [([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | [1, 1, 0] | [1, 1, 0] | Passed |
| oracle 1 | [2, 1, 0] | [2, 1, 0] | Passed |
| oracle 2 | [2, 2, 0] | [2, 2, 0] | Passed |
| oracle 3 | [1, 4, 0] | [1, 4, 0] | Passed |
| oracle 4 | [1, 1, 0] | [3, 1, 0] | Failed |
| oracle 5 | [2, 1, 20] | [4, 1, 20] | Failed |
| oracle 6 | None | None | Passed |
| oracle 7 | None | None | Passed |
SHA-256 / 7338336a9beddb8170c3c526b43e29c29252997d77b6296f9b00a366e9914200
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
ppq, sigs, tick = x
if tick < 0 or not sigs or sigs[0][0] != 0:
return None
start = 0
for k, (b, num, den) in enumerate(sigs):
beat = ppq * 4 // den
bar_len = beat * num
next_bar = sigs[k + 1][0] if k + 1 < len(sigs) else None
if next_bar is not None:
span = (next_bar - b) * bar_len
if tick >= start + span:
start += span
continue
offset = tick - start
return [b + offset // bar_len, offset % bar_len // beat + 1, offset % beat]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([480, [[0, 4, 4]], 0], [1, 1, 0]), ([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None)], [([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0])], [([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64])], [([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0])], [([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | [0, 1, 0] | [1, 1, 0] | Failed |
| oracle 1 | [1, 1, 0] | [2, 1, 0] | Failed |
| oracle 2 | [1, 2, 0] | [2, 2, 0] | Failed |
| oracle 3 | [0, 4, 0] | [1, 4, 0] | Failed |
| oracle 4 | [2, 1, 0] | [3, 1, 0] | Failed |
| oracle 5 | [3, 1, 20] | [4, 1, 20] | Failed |
| oracle 6 | None | None | Passed |
| oracle 7 | None | None | Passed |
SHA-256 / a1cbf7185c8bb53307048389d3044c3fea86db504e0a4f4568c1e6880ddd6920
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
ppq, sigs, tick = x
if tick < 0 or not sigs or sigs[0][0] != 0:
return None
start = 0
for k, (b, num, den) in enumerate(sigs):
beat = ppq * 4 // den
bar_len = beat * num
next_bar = sigs[k + 1][0] if k + 1 < len(sigs) else None
if next_bar is not None:
span = (next_bar - b) * bar_len
if tick >= start + span:
start += span
continue
offset = tick - start
return [b + offset // bar_len + 1, offset % bar_len // beat + 1, offset % beat]
return None
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([480, [[0, 4, 4]], 0], [1, 1, 0]), ([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None)], [([480, [[0, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0])], [([480, [[0, 4, 4]], 2400], [2, 2, 0]), ([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 3, 4]], 1450], [2, 1, 10]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64])], [([480, [[0, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0])], [([480, [[0, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 336], [2, 1, 0]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 1920], [2, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("oracle %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | [1, 1, 0] | [1, 1, 0] | Passed |
| oracle 1 | [2, 1, 0] | [2, 1, 0] | Passed |
| oracle 2 | [2, 2, 0] | [2, 2, 0] | Passed |
| oracle 3 | [1, 4, 0] | [1, 4, 0] | Passed |
| oracle 4 | [3, 1, 0] | [3, 1, 0] | Passed |
| oracle 5 | [4, 1, 20] | [4, 1, 20] | Passed |
| oracle 6 | None | None | Passed |
| oracle 7 | None | None | Passed |
SHA-256 / 560b74a601005573d593a61ef187278edacaa249141a47b6c78cee730c7ce641
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; it is not a complete Standard MIDI File or MIDI 1.0/2.0 implementation. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:50:03.795215+00:00.
Case digest / 6e9e9f8620ff30d02416fdf185d64630cc0b7fbf1aada2450e36f217ee9bc049