FAILURE MAP
← Case archive

FA-81536 / MIDI event timing / Open access

Bar, beat and tick position with meter changes: segment length measured from bar zero · case 01

With three meters, the middle segment is treated as starting from bar 0, so positions after the last change land in the wrong bar.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The length of a signature segment multiplies the next change's absolute bar index instead of the bar count in the segment.

VERIFIED REPAIR

Restore the segment span step so that it reads `(next_bar - b) * bar_len`.

Unsuccessful approach: Counting segment bars inclusively extends each segment by one bar.

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 * 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, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([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]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([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]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])]]
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 fixtureActualExpectedOutcome
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[2, 1, 0][2, 1, 0]Passed
oracle 5[4, 1, 0][4, 1, 0]Passed
oracle 6[4, 1, 0][4, 1, 0]Passed
oracle 7[4, 3, 200][4, 2, 200]Failed

SHA-256 / 845b14286f55d3282b7874b48bae2141ff16f80ead62ed43b6c01987b0704873

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 + 1) * 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, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([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]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([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]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])]]
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 fixtureActualExpectedOutcome
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[2, 1, 0][2, 1, 0]Passed
oracle 5[3, 4, 0][4, 1, 0]Failed
oracle 6[2, 3, 0][4, 1, 0]Failed
oracle 7[2, 5, 200][4, 2, 200]Failed

SHA-256 / b408297fd7d772559627e5e6cd18e63d749c64f5e4dc03810bbc69d4ef76024a

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, 6, 8]], 1440], [2, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 4320], [4, 1, 0]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([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]], 5300], [4, 1, 20]), ([480, [[0, 2, 2]], 1000], [1, 2, 40]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 2000], [5, 2, 20]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 3840], [3, 1, 0]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([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, [[1, 4, 4]], 0], None), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])], [([480, [[0, 4, 4], [2, 3, 4]], 5280], [4, 1, 0]), ([480, [[0, 4, 4], [2, 3, 4]], 5300], [4, 1, 20]), ([96, [[0, 7, 8], [1, 4, 4]], 400], [2, 1, 64]), ([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]), ([480, [[0, 4, 4], [1, 5, 8], [3, 4, 4]], 5000], [4, 2, 200]), ([120, [[0, 4, 4], [4, 6, 8], [6, 4, 4]], 3000], [7, 4, 0])]]
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 fixtureActualExpectedOutcome
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[2, 1, 0][2, 1, 0]Passed
oracle 5[4, 1, 0][4, 1, 0]Passed
oracle 6[4, 1, 0][4, 1, 0]Passed
oracle 7[4, 2, 200][4, 2, 200]Passed

SHA-256 / 4dc0f4579feb86297c14e7e613e764f0059d677df83e6a51239a68c0a976b5e5

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.838703+00:00.

Case digest / 8fce7efa8238bb4b92ed399674c47ac1bb45c3bea944057fbc268b225d7ecc5d