
Ein abhängigkeitsfreier C++-Player für Yamaha SMAF-Klingeltöne (.mmf): das polyphone Klingelton-Format der Handy-Chips MA-3/MA-5 aus den 2000er Jahren, neu aufgebaut mit einer eigenen ROM-freien FM-Engine. Der offene Player, den niemand fertiggestellt hat. Bewährt im FXChainPlayer.
von Akustikrausch (Andreas Wendorf)
ein kleiner, dependencies-freier Player für Yamaha-SMAF-Klingeltöne (.mmf) in c++.
Du gibst ihm eine dieser Dateien, die dein Samsung, Sharp oder Panasonic im Jahr 2004
deedle-deedle-dee machen ließen, und er gibt dir sauberes Stereo-Audio aus. Kein Telefon, keine
Firmware, keine Sample-ROM. Nur der FM-Chip, in Software nachgebaut.
Das ist der Sound eines gesamten Jahrzehnts, den fast niemand die Mühe gemacht hat, in offenem Code zu bewahren. Es gibt noch Millionen dieser Dateien, und niemand hat jemals einen offenen Player dafür fertiggestellt: Die Versuche blieben 2004 stecken oder umgehen den Synthesizer ganz. Also hier ist einer in c++, von Grund auf aus dem Format heraus geschrieben, mit einem eigenen FM-Synth-Kern.
🎧 Dieser Code wird in einem echten Produkt ausgeliefert: FXChainPlayer. Ein nativer Windows-Audioplayer, der deine alten Klingeltöne neben deinen FLACs, SIDs und Amiga-Modulen abspielt. Dort läuft diese Engine jeden Tag, gegen ein Korpus von Hunderten von echten Handy-Klingeltönen. Schnapp dir den Player zum Zuhören, oder lies weiter, wie der Chip funktioniert.
die Yamaha MA-Serie (YMU762 = MA-3, YMU765 = MA-5) war der Soundchip in
einem großen Teil der Handys der frühen 2000er. Es ist ein richtiger FM-Synthesizer, ein enger Verwandter
der OPL/OPN-Chips aus der Adlib- und Sega-Genesis-Ära, verkleinert für ein
Mobilgerät. Die Dateien, die er abspielte, SMAF (.mmf), enthalten eine FM-Partitur plus optionale
ADPCM-Samples. Der polyphone Klingelton wurde hier geboren.
dann kamen Smartphones, MP3-Klingeltöne übernahmen, und das gesamte Format starb leise. Yamaha nahm sein SDK offline. Und anders als in der Amiga- oder C64-Szene hat fast niemand einen Emulator geschrieben. Was existiert:
umjammer/vavi-sound (Java) parst und spielt SMAF und ist eine brillante Verhaltensreferenz, macht aber überhaupt keine FM-Synthese: Es verpackt die Töne als General MIDI neu und lässt Javas Synthesizer sie approximieren. Und es ist Java.Es gab also keinen nativen, freizügig lizenzierten, ROM-freien Player des tatsächlichen FM-Chips. Das ist er. Jedes Byte des Parsers und jeder Operator des Synthesizers wurde aus der öffentlichen SMAF-Formatbeschreibung plus vielem Starren auf echte Dateien in einem Hex-Editor geschrieben, nie durch Kopieren eines anderen Players.
die Engine besteht aus fünf kleinen Teilen, die jeweils für sich testbar sind:
src/
smaf_file the MMMD container: big-endian TLV chunks (CNTI/OPDA/MTR/ATR),
two score generations (HandyPhone for MA-1/2, Mobile for MA-3/5)
ma_player the two event decoders (+ okumura huffman for the packed
variant), a scheduler that runs in milliseconds like the chip
did, and the render loop that drives a pool of FM voices
ma_fm_core the FM DSP: 2-op and 4-op operators, exponential ADSR envelopes,
the OPL-style connection algorithms, and its own general-midi
approximation patch bank
smaf_voice decodes the yamaha voice sysex blobs (VM35 for MA-3/5, VMA for
MA-1/2) into FM patches, including the MA-3 bit-packed form
yamaha_adpcm the YM2608-family 4-bit adpcm codec, for the sampled voices
Das Timing-Modell ist die nette Überraschung: SMAF hat keine Tempo-Events, die Zeit ist rein metrisch (Event-Zeit = Summe der Dauern multipliziert mit einer Zeitbasis, in Millisekunden), also bildet ein Tick direkt auf eine Millisekunde und dann auf Samples ab. Der FM-Kern läuft direkt mit deiner Ausgaberate, es gibt also kein Resampling auf dem Synth-Pfad.
die MA-Chips enthielten auch eine kleine General-MIDI-Sample-ROM, damit ein Klingelton "Programm 5 spielen" sagen konnte und ein Preset-Klavier bekam. Diese ROM gehört Yamaha, wurde nie öffentlich gedumpt, und dieses Projekt liefert sie nicht aus, will sie nicht und wird sie niemals bündeln. Das ist eine harte Linie.
Stattdessen trägt ma_fm_core seine eigene handgebaute FM-Patch-Bank, die die ROM ersetzt: Eine Datei, die nach "Programm 5" fragt, bekommt eine plausible FM-Stimme der richtigen Familie. Es wird nicht bit-identisch zu einem Handy von 2003 sein, und das ist der ehrliche Kompromiss. Was du bekommst, ist die echte FM-Partitur, das echte Noten-Timing, die echte ADSR, gespielt von einem eigenen Synthesizer. Erkannt, und es spielt.
Dateien, die ihre eigenen benutzerdefinierten Stimmen enthalten (viele tun das), klingen genau wie erstellt, weil diese Stimmen in der Datei leben, nicht in der ROM.
cmake -B build && cmake --build build
./build/smaf-render your_ringtone.mmf out.wav 30
oder binde die Bibliothek in deinen eigenen Code ein:
#include "smaf_file.h"
#include "ma_player.h"
using namespace fxchain::smaf;
SmafFile file;
file.parse(bytes.data(), bytes.size()); // MMMD container
MaPlayer player;
player.init(file, 44100); // build voices + decode the score
float buf[1024 * 2]; // interleaved stereo
int frames = player.render(buf, 1024); // pump the synth
43 79 06 7F 03), in dem einige reine Drum-Kit-Dateien ihre Samples tragen; und die SD-1-spezifischen höheren Wellenformen. Siehe ROADMAP.md..mld)-Format (ein Cousin; siehe ROADMAP.md m3).dieser Parser ist dafür gedacht, nicht vertrauenswürdige Dateien zu fressen, daher ist er defensiv geschrieben: Jede Chunk-Länge wird auf den tatsächlichen Puffer begrenzt, die Huffman-Inflation hat Knoten- + Tiefenschutz und eine Ausgabeobergrenze, und die Event-Decoder haben Iterations- + Gesamtereignis-Obergrenzen. Es degradiert zu "keine gültige SMAF-Datei", anstatt abzustürzen. Details und Meldung in SECURITY.md.
src/ die Engine (vier kleine Übersetzungseinheiten plus ein Header-Only-Codec, keine Abhängigkeiten). example/smaf-render.cpp das WAV-CLI in unter 100 Zeilen. CMakeLists.txt baut eine statische smaf-Bibliothek plus das Beispiel. Das ist alles.
Apache License 2.0 (siehe LICENSE). Der Parser und der Synthesizer sind originäre Arbeit; es wird kein Code Dritter mitgeliefert, und es ist kein Yamaha-ROM- oder SDK-Material enthalten. Das Formatwissen stammt aus der öffentlichen SMAF-Spezifikation und Beobachtung.
nicht verbunden mit, autorisiert von oder unterstützt durch Yamaha. "SMAF" und die MA-Chipnamen sind Eigentum von Yamaha. Dies ist Interoperabilitätsarbeit: Ein unabhängiger Player eines offenen Dateiformats, gebaut ohne jeglichen Yamaha-Code oder die geschützte Sample-ROM.
Grüße an alle, die sich noch erinnern, wie ihr Klingelton klang.