FAILURE MAP
← Case archive

FA-80871 / Music interval and transposition theory / Open access

Key-aware MIDI note spelling: C major chromatic notes spelled with flats · case 01

In a key with no sharps or flats, key 61 is spelled Db4 instead of the stipulated C#4.

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

ROOT CAUSE

The flat-side test includes fifths == 0, moving the neutral key to flat spellings.

VERIFIED REPAIR

Restore the flat side boundary step so that it reads `flats if f < 0 else sharps`.

Unsuccessful approach: Moving the boundary to -1 fixes C major but makes F major (one flat) spell chromatic notes with sharps.

Case contract

Input [midi, fifths] with midi 0..127 and fifths -7..7. Use flat names when fifths < 0, sharp names otherwise; in keys with at least six sharps pitch class 5 is E#, with seven sharps pitch class 0 is B# of the previous octave, and with at least six flats pitch class 11 is Cb of the next octave. Octave -1 starts at key 0. Invalid input returns None.

Why this case matters

Pitch spelling and interval arithmetic decide the notes that notation, transposition and analysis tools display or play.

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) != 2:
        return None
    m, f = x
    if not isinstance(m, int) or m < 0 or m > 127:
        return None
    if not isinstance(f, int) or f < -7 or f > 7:
        return None
    sharps = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    flats = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']
    table = flats if f <= 0 else sharps
    pc = m % 12
    octave = m // 12 - 1
    name = table[pc]
    if f >= 6 and pc == 5:
        name = 'E#'
    if f == 7 and pc == 0:
        name = 'B#'
        octave -= 1
    if f <= -6 and pc == 11:
        name = 'Cb'
        octave += 1
    return name + str(octave)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 0], 'C4'), ([61, 0], 'C#4'), ([61, -1], 'Db4'), ([61, 1], 'C#4'), ([70, -2], 'Bb4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([65, 5], 'F4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([60, 7], 'B#3'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([71, -7], 'Cb5'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([1, -3], 'Db-1'), ([11, 0], 'B-1'), ([127, 0], 'G9'), ([63, -1], 'Eb4')]]
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 0C4C4Passed
oracle 1Db4C#4Failed
oracle 2Db4Db4Passed
oracle 3C#4C#4Passed
oracle 4Bb4Bb4Passed
oracle 5A#4A#4Passed
oracle 6E#4E#4Passed
oracle 7Eb4Eb4Passed

SHA-256 / b8f510d4041cedb61eeb8e28d806a56a3ce41abee9aaab6f936d0ef57ee412cd

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) != 2:
        return None
    m, f = x
    if not isinstance(m, int) or m < 0 or m > 127:
        return None
    if not isinstance(f, int) or f < -7 or f > 7:
        return None
    sharps = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    flats = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']
    table = flats if f < -1 else sharps
    pc = m % 12
    octave = m // 12 - 1
    name = table[pc]
    if f >= 6 and pc == 5:
        name = 'E#'
    if f == 7 and pc == 0:
        name = 'B#'
        octave -= 1
    if f <= -6 and pc == 11:
        name = 'Cb'
        octave += 1
    return name + str(octave)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 0], 'C4'), ([61, 0], 'C#4'), ([61, -1], 'Db4'), ([61, 1], 'C#4'), ([70, -2], 'Bb4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([65, 5], 'F4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([60, 7], 'B#3'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([71, -7], 'Cb5'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([1, -3], 'Db-1'), ([11, 0], 'B-1'), ([127, 0], 'G9'), ([63, -1], 'Eb4')]]
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 0C4C4Passed
oracle 1C#4C#4Passed
oracle 2C#4Db4Failed
oracle 3C#4C#4Passed
oracle 4Bb4Bb4Passed
oracle 5A#4A#4Passed
oracle 6E#4E#4Passed
oracle 7D#4Eb4Failed

SHA-256 / 38a2b8c9bf3481c38e7761bf05a828984d78977d3e05d2eafd0aa39b347b3108

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) != 2:
        return None
    m, f = x
    if not isinstance(m, int) or m < 0 or m > 127:
        return None
    if not isinstance(f, int) or f < -7 or f > 7:
        return None
    sharps = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    flats = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']
    table = flats if f < 0 else sharps
    pc = m % 12
    octave = m // 12 - 1
    name = table[pc]
    if f >= 6 and pc == 5:
        name = 'E#'
    if f == 7 and pc == 0:
        name = 'B#'
        octave -= 1
    if f <= -6 and pc == 11:
        name = 'Cb'
        octave += 1
    return name + str(octave)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([60, 0], 'C4'), ([61, 0], 'C#4'), ([61, -1], 'Db4'), ([61, 1], 'C#4'), ([70, -2], 'Bb4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([70, 2], 'A#4'), ([65, 6], 'E#4'), ([65, 5], 'F4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([65, 7], 'E#4'), ([65, -6], 'F4'), ([60, 7], 'B#3'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([48, 7], 'B#2'), ([71, -6], 'Cb5'), ([71, -7], 'Cb5'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([63, -1], 'Eb4')], [([61, 0], 'C#4'), ([61, -1], 'Db4'), ([59, -6], 'Cb4'), ([0, 0], 'C-1'), ([1, -3], 'Db-1'), ([11, 0], 'B-1'), ([127, 0], 'G9'), ([63, -1], 'Eb4')]]
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 0C4C4Passed
oracle 1C#4C#4Passed
oracle 2Db4Db4Passed
oracle 3C#4C#4Passed
oracle 4Bb4Bb4Passed
oracle 5A#4A#4Passed
oracle 6E#4E#4Passed
oracle 7Eb4Eb4Passed

SHA-256 / 0c0849ba34310cf81657d7f23053e1c43fe77c388e2763a90b66d4478acaaf2c

Verification & scope

A deterministic bounded teaching model with a stipulated toy contract; it is not a complete music notation or theory engine. 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:49:57.949204+00:00.

Case digest / 13a06bbe3013c32f1349d88cc047bf1bdc697c6faa643e9cdb2b682e4e7c1e69