FAILURE MAP
← Case archive

FA-81521 / MIDI event timing / Open access

Bar, beat and tick position with meter changes: every beat treated as a quarter note · case 01

In 6/8 the fourth eighth-note beat is reported as beat 2 because beats are measured in quarters.

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

ROOT CAUSE

The beat length ignores the time-signature denominator.

VERIFIED REPAIR

Restore the beat length unit step so that it reads `ppq * 4 // den`.

Unsuccessful approach: Scaling by den/4 instead of 4/den makes eighth-note beats twice a quarter instead of half.

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
        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, 3, 4]], 1450], [2, 1, 10]), ([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])], [([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]), ([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]], 720], [1, 4, 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, 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, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 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]], 4320], [4, 1, 0]), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100])], [([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]], 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, 2, 240][1, 4, 0]Failed
oracle 4[2, 1, 10][2, 1, 10]Passed
oracle 5[3, 1, 0][3, 1, 0]Passed
oracle 6[2, 1, 40][1, 2, 40]Failed
oracle 7[1, 4, 48][2, 1, 0]Failed

SHA-256 / 4f77f001ad3b340d5a5a9ef97b3625464d1d07a02d6ea33bc09e027812ecb9e7

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 * den // 4
        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, 3, 4]], 1450], [2, 1, 10]), ([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])], [([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]), ([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]], 720], [1, 4, 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, 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, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 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]], 4320], [4, 1, 0]), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100])], [([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]], 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, 1, 720][1, 4, 0]Failed
oracle 4[2, 1, 10][2, 1, 10]Passed
oracle 5[3, 1, 0][3, 1, 0]Passed
oracle 6[3, 1, 40][1, 2, 40]Failed
oracle 7[1, 2, 144][2, 1, 0]Failed

SHA-256 / 420d43e2fd4078a347717f75befb6fa45faa3cf30d70ab878b83a5252feb7684

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, 3, 4]], 1450], [2, 1, 10]), ([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])], [([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]), ([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]], 720], [1, 4, 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, 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, 6, 8]], 720], [1, 4, 0]), ([480, [[0, 6, 8]], 1440], [2, 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]], 4320], [4, 1, 0]), ([480, [[0, 4, 4]], -5], None), ([480, [[0, 3, 16]], 700], [2, 3, 100])], [([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]], 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, 10][2, 1, 10]Passed
oracle 5[3, 1, 0][3, 1, 0]Passed
oracle 6[1, 2, 40][1, 2, 40]Passed
oracle 7[2, 1, 0][2, 1, 0]Passed

SHA-256 / 6604ac18d92a1977910134199f1657a962745fe5e16f5c2ebe34e7a87a7dadb8

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

Case digest / 9af8d43436b82ec1841bda5bf5237ef93ae8e1c72cfa051a797498dab4eb7140