Mark I OPS recalibration — plan + divisor A/B harness (markI-ops-dac findings 1–3)#15
Conversation
… findings 1-3) Investigation artifacts for the Mark I OPS forward-mod darkness recalibration (decision pending, by ear). Adds MarkIDivisorABTests (renders BASS 1 + E.PIANO 1 through the full SynthEngine at div4/5/6/8 + Modern, peak-normalized WAVs + sustain centroid) and docs/mark-i-recalibration-plan.md framing the coordinated fix (findings 1 output-scale, 2 divisor, 3 feedback), the KLS/darkerSustain interaction, A/B data, and a recommendation. No shipping code changed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…< Modern; env-gate A/B An A/B by ear found ÷4-8 nearly indistinguishable (data: BASS 1 ~12% centroid spread, E.PIANO 1 divisor-insensitive), so the shipping Mark I forward-mod divisor stays ÷5 — markI-ops-dac finding 2 is closed as a low-impact calibration. Findings 1 (12 dB output) & 3 (feedback) remain deferred. - MarkICalibrationTests.darkerSustain: drop the stale ÷0.6 'markedly darker' threshold (an artifact of the pre-KLS-fix over-bright Modern); assert only Mark I < Modern. - MarkIDivisorABTests: env-gate behind M2DX_MARKI_AB so it no-ops in a normal swift test (it mutates the process-global markIModScaleQ12 and was racing the Mark I parity suite under the parallel runner); restore the ÷8 default on exit. - docs/mark-i-recalibration-plan.md: record the decision. 241 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10abda3644
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) | ||
|
|
||
| let bass1 = DX7SysExParser.parse(data: bankFromVoice(rom1aBass1Packed), bankName: "ROM1A")!.presets[0] | ||
| let epiano1 = DX7FactoryPresets.all[11] // ROM1A E.PIANO 1 (alg 4, feedback) |
There was a problem hiding this comment.
Use the actual E.PIANO 1 preset
In this A/B harness, DX7FactoryPresets.all is built as [initVoice] + customPresets, and keysBatch starts with E.PIANO 1, so index 11 selects TINE BELL rather than E.PIANO 1. That means the generated WAVs and the calibration data documented as E.PIANO 1 are for the wrong patch, which can lead the divisor decision to be based on an unrelated bell preset; select the named preset or the correct index instead.
Useful? React with 👍 / 👎.
What
Investigation artifacts for the Mark I OPS forward-modulation ("darkness") recalibration raised by the DX7 fidelity audit (
markI-ops-dacfindings 1–3). No shipping code is changed yet — this is the plan + A/B evidence so the forward-mod divisor can be chosen by ear, then implemented (TDD) on this branch.docs/mark-i-recalibration-plan.md— frames the coordinated fix (finding 1<<13output scale, finding 2 mod divisor, finding 3 feedback), the KLS /darkerSustaininteraction, the A/B data, and a recommendation + implementation plan.Tests/M2DXCoreTests/MarkIDivisorABTests.swift— renders BASS 1 (alg 15) + E.PIANO 1 (alg 4) through the fullSynthEngineat ÷4/÷5/÷6/÷8 + Modern, writes peak-normalized WAVs (compare timbre, not loudness) + prints the sustain spectral centroid. Run:swift test --filter renderMarkIDivisorAB→/tmp/m2dx-marki-ab/.A/B data (note 60, −3 dBFS normalized, sustain centroid — lower = darker)
Status
Decision pending (by ear). Once the divisor + scope are chosen, the implementation plan in the doc lands here (TDD:
markIModScaleQ12default, optional<<13→<<11+ feedback,darkerSustainre-baseline,dx7refmkiparity kept green), then a new M2DX-Core release + app pin bump + on-device A/B. Clean-room preserved (no GPLEngineMkI.cppconsulted).Follows the
keyboard-scalingfix in #14 (v1.16.0).🤖 Generated with Claude Code