Skip to content

Add MA-7 SMAF/SEQU decoding support - #290

Merged
psi29a merged 7 commits into
masterfrom
ma7
Jul 27, 2026
Merged

Add MA-7 SMAF/SEQU decoding support#290
psi29a merged 7 commits into
masterfrom
ma7

Conversation

@psi29a

@psi29a psi29a commented Jul 27, 2026

Copy link
Copy Markdown
Member

Add MA-7 SMAF support (score + FM voices)

MA-7 .mmf files previously failed to play. This decodes both halves of the format and fixes the bank lookup that kept them silent.

SEQU score (format_type 0x03)

Not a compressed format as previously assumed — it's Mobile Standard with the status byte repacked for 32 channels:

  • bit 7 = channel bank (0-15 / 16-31), bits 6-4 = event type (MIDI nibble 0x8+n), bits 3-0 = channel low nibble
  • 0xF0/0xFF literal; no running status (status bytes are < 0x80)
  • Reuses the Mobile decoder via a sequ flag

Explains the old "mystery 0x61 record": pitch bend on ch1 + the next duration byte.

MA-7 FM voices (43 79 08 7F 21)

Operators are stored in the chip's native 10-byte layout, not packed 7-byte VM35: MULTI/DT → byte 9, WS/FB → byte 6, bytes 5/7/8 reserved. Undoing the shuffle reuses the existing VM35 decoder.

Bank fallback (src/patches.c)

  • SMAF selects Yamaha voice banks (0x7c) that no GUS/SF2 set defines; _WM_get_patch_data had no fallback → silence
  • Now falls back to bank 0, as hardware does
  • Pre-existing bug: any SMAF file without custom FM voices was mute (MA-5 only escaped via MAFM)

Verification

Both decodes checked against Yamaha's MCP-MA7 middleware (Ghidra + Unicorn, clean-room; the DLL is 32-bit x86 so it emulates directly, no Wine).

  • Voice mapping round-trips through Yamaha's packer: 20/20 operator bytes exact, all 4 corpus voices
  • Decoded params are textbook 2-op FM (carriers TL=0/MULTI=1); earlier guesses gave MULTI=0 on both ops, which no real patch has
  • SEQU parse byte-exact on both MA-7 files; pitch classes cleanly diatonic
  • Corpus re-render: 30/32 bit-identical, only the two MA-7 files change
  • 2 new tests (smaf_sequ, ma7_voice), 3/3 pass

Limitations

  • MA-7 FM voices: only body form 0x00 is decoded — 10 of the 58 voice
    records across the 5 known MA-7 files. p[10] selects the form; 0x01
    (plain VM35), 0x02, 0x03 and 0x07 are declined rather than guessed,
    and those voices fall back to GM. Form 0x00 is not the common case —
    form 0x03 is (36/58). Per file: AB00221GM7/AB03957GM7 get all their
    voices, Blossom gets 2 of 25, AccidentCafe7 none, First Love has no
    voice records (streaming Mtsp).
  • MA-7 native operator bytes 5/7/8 hold MA-7-only parameters with no VM35
    equivalent; they're ignored, so those voices lose whatever those fields do.
  • Channels 16-31 fold onto MIDI's 16 — no known file plays on them.
  • Possible constant octave offset in SEQU notes unresolved; notes pass through
    unchanged.
  • Pre-existing, unchanged: Huffman-compressed Mobile (format_type 0x01) is
    not decompressed, and MA-3/MA-5 PCM (sampled) voices are parsed but not
    played.
  • No other open-source implementation reads MA-7 correctly (vavi-sound and
    smaf825 both route it to their HandyPhone decoder), so there was nothing to
    cross-check against. docs/formats/SmafFileFormat.txt records the
    derivation, the corpus sources, and what was ruled out.

From AB00221GM7.MMF and AB03957GM7.MMF
AB00221GM7.mp3
AB03957GM7.mp3

psi29a added 4 commits July 27, 2026 10:04
MA-7 stores operators in the chip's native 10-byte layout rather than the
packed 7-byte VM35 one: MULTI/DT moves to byte 9, WS/FB to byte 6, and
bytes 5/7/8 are reserved. Undoing that shuffle reuses the existing VM35
decoder, so MA-7 files now play on the FM engine instead of falling back
to the GM wavetable.
@psi29a

psi29a commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

@CodeRabbit summary

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 508ed3bd-3f31-4b3b-b835-207140c659ab

📥 Commits

Reviewing files that changed from the base of the PR and between 474b549 and 01d2ef4.

📒 Files selected for processing (1)
  • docs/formats/SmafFileFormat.txt
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/formats/SmafFileFormat.txt

📝 Walkthrough

Walkthrough

Adds MA-7 SEQU score-track decoding, MA-7 FM voice-exclusive decoding, format documentation, regression tests, and bank-0 fallback lookup for missing non-zero-bank patches.

Changes

MA-7 SMAF support

Layer / File(s) Summary
SEQU format contract
docs/formats/SmafFileFormat.txt
Documents MA-7 container mappings, required Mtsq tracks, format 0x03, packed channel status bytes, and SEQU event mappings.
SEQU score conversion
src/smaf2mid.c, test/CMakeLists.txt, test/test_smaf_sequ.c
Decodes SEQU events, remaps 32 logical channels onto 16 MIDI channels, and verifies generated MIDI events.
MA-7 FM voice decoding
src/mafm/smaf_voice.c, test/CMakeLists.txt, test/test_ma7_voice.c, docs/formats/SmafFileFormat.txt
Decodes supported MA-7 FM forms by reconstructing VM35-style operator data and tests sampled-form rejection.

Bank fallback lookup

Layer / File(s) Summary
Bank-0 fallback lookup
src/patches.c
Retries bank-0 patch lookup when a requested non-zero bank has no matching patch.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MMF
  participant _WM_smaf2midi
  participant decode_mobile
  participant MIDI
  MMF->>_WM_smaf2midi: MA-7 format_type 0x03 track
  _WM_smaf2mid->>decode_mobile: Pass SEQU decoding flag
  decode_mobile->>MIDI: Emit repacked MIDI events
Loading

Possibly related PRs

Suggested reviewers: sezero

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding MA-7 SMAF/SEQU decoding support.
Description check ✅ Passed The description is directly related to the PR and summarizes the SEQU, FM voice, and bank-fallback changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
✅ Action performed

Summary regeneration triggered.

@psi29a psi29a changed the title Ma7 Add MA-7 SMAF/SEQU decoding support Jul 27, 2026
@psi29a
psi29a requested a review from sezero July 27, 2026 09:36
p[10] selects the MA-7 voice body layout; only form 0x00 (3 global +
10 bytes/operator) is established, so require it and an exact body
length instead of assuming every 7F 21 record uses that shape. Also
drop the bogus voice-type reading of p[9], which holds split points.

@sezero sezero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Built and played cleanly. My valgrind was silent.

@psi29a

psi29a commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

Built and played cleanly. My valgrind was silent.

Awesome, I just found a stash of 1000+ MMF files; I'm now iterating over all of them to make sure they play and nothing blows up (smoke test). Might be some more missing features.

The cool news is that no other FOSS player on the planet supports MA-7 based files. :)

psi29a added 2 commits July 27, 2026 12:34
p[10] is effectively the voice type: forms 0x00 and 0x02 are FM and
share the 3-global + 10-byte-operator layout (0x02 adds a 16-byte
trailer), while 0x01/0x03/0x07 are sampled voices whose bodies start
with a PCM sample rate. Decoding 0x02 covers every FM voice in every
known MA-7 file. Also document the MA-1..MA-6 gaps in SMAF_TODO.md.
@psi29a
psi29a merged commit fbe6482 into master Jul 27, 2026
23 checks passed
@sezero
sezero deleted the ma7 branch July 27, 2026 11:11
@coderabbitai coderabbitai Bot mentioned this pull request Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants