Firmware

FMLarynx

Loud82/100

A throaty talking formant synth with a 303-style pattern sequencer: The synth is a saw wave through a three-formant vowel filter with an envelope, an added resonant LPF with cutoff and a ping-pong del

FMLarynx is custom firmware for the M-VAVE FM-1, by @ejtb76. Open source under GPL-3.0, latest release v0.1.1 (October 2026), 1 star on GitHub.

forM-VAVE FM-1·by@ejtb76

Unclaimed. Is this yours? Sign in with GitHub as @ejtb76 to claim it.

Downloads
0
Star
1
Forks
0
Commits
24
Last commit
Download v0.1.1

fmlarynx-0.1.1.fwsc· 596 KB· +1 file

GPL-3.0· ejtb76/FMLarynx·fm1.designburgapps.com·downloads come from the creator’s GitHub releases

24
Commits
2
Releases
24 commits and 2 releases in the last year
Activity · last 12 months

FMLarynx

A formant synthesizer firmware for the M-VAVE FM-1.

A throaty talking formant synth with a 303-style pattern sequencer: The synth is a saw wave through a three-formant vowel filter with an envelope, an added resonant LPF with cutoff and a ping-pong delay with drive. The 16-step sequencer has vowels, accent and slide per step, a pattern randomizer and storage for 16 patterns.

It is a port of FormantSynth, a VST3 plugin, to the FM-1's chip, and is built on Dinghy by zvenson.

FMLarynx's screen: a throat whose opening follows the vowel, the note in it, the step strip and the keyboard

Status: 0.1, runs on the FM-1. Tested on the device: the sound engine, all controls, the sequencer with its randomizer and stored patterns, the effects, the screen, and updating over USB.

What it keeps: FMLarynx stores its patterns and settings in the FM-1's settings sector, the place Felucca, SLOOP, Dinghy and their relatives use for theirs: after one of them has run, FMLarynx starts from its defaults again (and the other way round). It does not read other firmwares' projects or samples.

Package identity: FM-1_984, for every release.

The sound

One voice, three formants:

  • Source: a sawtooth, harmonically rich, with a short attack (~5 ms) and release (~45 ms).

  • Filter: three resonant band-pass filters in parallel, tuned to the first three formants (F1, F2, F3) of a vowel.

  • Vowel plane: the five vowels i, e, a, o, u sit on a plane of the two things your mouth does for a vowel: Tongue (front for i and e, back for o and u) and Jaw (closed for i and u, wide open for a). Anywhere between them, the formant frequencies blend smoothly, so turning Tongue and Jaw morphs one vowel into the next.

    Jaw
    open         a
           e           o
    closed i           u
         front       back   Tongue
    
  • Voice: moves the formants from an adult male vocal tract to a female/child one.

  • Size: scales all formants up or down (0.5x to 2x), from a giant's throat to a tiny one.

  • Resonance: how narrow and ringing the formants are. Output is compensated so the volume stays roughly level as you turn it up.

  • Cutoff: a resonant low-pass filter after the formants (12 dB/octave), from 60 Hz to fully open. Its resonance follows the Resonance knob (Q 0.7 to 8), one resonance for formants and filter as on a 303, and accents sharpen it too.

  • Effects: Drive, a soft-clipping distortion after the voice, and a tempo-synced ping-pong Delay: the echoes alternate left and right, each a little darker, and ring out after the notes stop.

  • Envelope (TB-303 style): every new note restarts it. Env Mod sets how far it opens the cutoff (up to 4 octaves) and the formant size (up to 2x); Decay how fast it closes again. Amp Decay lets the volume die away too.

  • Accent: an accented note is louder, and briefly raises the resonance and pulls the vowel towards "a".

Everything runs in integer maths (the chip has no FPU); the audio routine uses well under its time budget.

The screen

The top of the screen looks down a throat: rings of flesh from pink to deep red, the uvula hanging from above, the tongue below, teeth along the edge, and the note you play in the opening. The opening follows the vowel: tall and wide for "a", a flat slit for "i", small and round for "u", and everything in between as you turn Tongue and Jaw or the LFOs move them. On an accent the uvula wobbles.

Below it: the step strip (see the sequencer), the keyboard with the keys that sound, the last control you turned with its value, and the octave.

Controls

No menus: every parameter has its own encoder. The LFO, ENV and FX buttons turn knobs 1 to 4 into the LFO, envelope or effect controls for as long as you hold them.

Encoders

ControlNormallyWhile holding LFOWhile holding ENVWhile holding FX
KNOB 1Size, 500 to 2000 (0.5x to 2x)Tongue LFO rate, 0 to 1000 (0 to 8 Hz)Decay, 0 to 1000 (30 ms to 2 s)Delay mix, 0 to 1000 (0 = off)
KNOB 2Resonance, 10 to 500 (Q 1 to 50)Tongue LFO depth, 0 to 1000Env Mod, 0 to 1000Delay feedback, 0 to 1000
KNOB 3Voice, 0 to 1000 (male to female/child)Jaw LFO rate, 0 to 1000 (0 to 8 Hz)Accent amount, 0 to 1000Delay time: 1/16, 1/8, 3/16, 1/4, 3/8
KNOB 4Cutoff, 0 to 1000 (60 Hz to open)Jaw LFO depth, 0 to 1000Amp Decay, 0 to 1000 (30 ms to 2 s; 1000 holds)Drive, 0 to 1000
ALGORITHMTongue, 0 to 1000 (front to back)
SELECTJaw, 0 to 1000 (closed to open; see the sequencer for its other jobs)
PRESETSJump to a vowel: i, e, a, o, u (in record mode: the cursor step's vowel)
MASTERVolume

At power-on: Cutoff open, Env Mod 0, Decay 500, Accent 1000, Amp Decay 1000, Drive 0, Delay mix 0 (3/16, feedback 400), so the envelope and the effects are out of the way until you dial it in.

The tongue LFO moves the tongue, the jaw LFO the jaw, each around where the encoders put it. The screen shows the name and value of the last control you turned.

Buttons and keys

ControlWhat it does
KeysPlay the voice (27 keys, F3 to G5 at octave 0). Monophonic: the last note played wins.
OCT- / OCT+Octave, -2 to +2. The button lights when you're off centre. (With SEQ held: transpose the pattern.)
LFOHold to set the LFOs with knobs 1 to 4. Glows softly as a reminder, lights up while held.
ENVHold to set the envelope with knobs 1 to 4; glows softly, lights up while held. In record mode it also marks accents.
RECSequencer record mode on/off.
PLAYStart/stop the sequencer.
GLOIn record mode: marks slides (it only glows there).
SELHold and press a white key: load a stored pattern. Tapped in record mode: enters a rest.
SAVEHold and press a white key: store the pattern there (16 places).
SEQHold and turn SELECT to set the tempo; hold and press a key or OCT to transpose the pattern.
ARPThe pattern randomizer: hold it and press PLAY, a key or turn SELECT (see below).
FXHold to set the effects with knobs 1 to 4; glows softly, lights up while held.

Sequencer

A 16-step pattern sequencer in the spirit of the TB-303, so both hands are free for the knobs while it plays. Each step is a 16th note.

Recording a pattern

  1. Press REC. Playback stops and the cursor goes to step 1. The 16 white keys now show the 16 steps.
  2. Turn SELECT to move the cursor to a step.
  3. Press a key: its note goes into that step and the cursor moves on to the next one. Hold GLO and/or ENV while pressing the key to make that step a slide and/or an accent.
  4. Press REC again to leave record mode.

You hear every note as you enter it. A step without a note is a rest: tap SEL to enter one (it clears the cursor step and moves on, like a key does), so notes and rests go in one after the other. To change a step, move the cursor to it and record over it, or tap SEL to clear it. To add or remove a slide or accent afterwards, move the cursor to the step and tap GLO or ENV on its own: it toggles on release, and only if you didn't press a key or turn SELECT while holding it.

A vowel per step: in record mode, turn PRESETS to give the cursor step its own vowel (-, i, e, a, o, u; - = none). There is nothing to confirm: the step has it as you turn, and the throat shows it. While the pattern plays, a step with a vowel glides there; steps without one follow the Tongue and Jaw knobs, and the LFOs work on top of both. Recording a note over a step keeps its vowel; SEL clears it with the rest.

Notes and slides, as on a 303: a note sounds for half its step, then lets go. A slide on a step holds its note into the next step, which then glides there in pitch (in ~50 ms) without restarting the envelope.

Accents: louder, with a short burst of resonance and a vowel shift towards "a"; ENV + KNOB 3 sets how much.

On the screen: a strip of 16 cells above the keyboard shows the pattern, each cell over its own white key: dark = rest, pale = a note, pink = an accented note, a tiny letter = the step's vowel, a bar running into the next cell = a slide, and a red tick under the cursor (record mode) or under the step that is playing.

The lights in record mode

White keyMeans
OffEmpty step (a rest)
SoftThe cursor
MediumA step with a note in it
FullThe note sounding right now
GLO / ENV fullThe step under the cursor is a slide / an accent

While the pattern plays, GLO and ENV light up on every step that has a slide or an accent.

Playing: press PLAY. Hold SEQ and turn SELECT to set the tempo (40 to 300 BPM, 120 by default).

Random patterns: hold ARP and

  • press PLAY: a new random pattern, heard from the next step if it is playing (it doesn't start or stop it);
  • press a key: that note becomes the root, and a pattern on it comes right away;
  • turn SELECT: the scale, one of MIN PENTA, MINOR, PHRYGIAN, DORIAN, MAJOR, CHROMATIC.

The notes come from the scale over the root, two octaves up, with the root and its octave the most likely; step 1 is always the root. About a quarter of the steps are rests, a fifth slides and a quarter accents, and about 30% of the notes get a vowel of their own (the rest follow the knobs and the LFOs). Root and scale are kept with the pattern.

MIDI clock: when a DAW or another device sends MIDI clock over USB, the sequencer follows it, and MIDI start, stop and continue start and stop it. If the clock stops for half a second, it carries on at its own tempo.

Transpose: hold SEQ and press a key: the pattern moves so that its first note lands on that key (press that first note itself to go back). SEQ + OCT- / OCT+ moves it an octave. It is live: the stored notes stay as they are, the change is heard from the next step, and it goes back to 0 when you load a pattern or pick a new root with ARP + a key (not with ARP + PLAY, so you can jam on in the same key). Not kept after power-off.

Stored patterns: hold SAVE and press a white key to store the pattern (notes, slides, accents, vowels, root and scale) in one of 16 places; hold SEL and press a white key to load one. While the sequencer plays, a load waits for the next step 1, so the switch lands on the beat. While SAVE or SEL is held, the white keys show the places: middle = stored, full = the one last saved or loaded. The tempo is the same for all of them.

Saved: the pattern, the 16 stored patterns, the tempo, the octave, and the randomizer's root and scale are kept in flash and come back after power-off. They are saved two seconds after your last change, once the sequencer is stopped and nothing is sounding, because writing to flash briefly interrupts the sound. Stop the sequencer for a moment before you switch off, so your last changes are saved.

MIDI and audio over USB

  • MIDI in: notes on any channel play the voice, with velocity. MIDI clock drives the sequencer.
  • MIDI out: notes from the keys and from the sequencer.
  • Audio: the FM-1 shows up as a 16-bit stereo audio input (44.1 or 48 kHz), so you can record it straight into a DAW.

Installing

Installing custom firmware is at your own risk. The easy way is the FM-1 Firmware Hub in Chrome or Edge: it installs a release in one click, and takes you back to the official firmware or to another one the same way. Or download the .fwsc from this repository's releases.

To build it yourself, then install over USB:

./build.sh                                       # -> build/fmlarynx.fwsc
python3 tools/fm1_install.py build/fmlarynx.fwsc   # asks before it writes, then restarts into the new build
python3 tools/fm1_install.py --info              # what runs on the connected FM-1

The build needs Linux on x86-64 (or Windows with WSL, or macOS with Docker), Python 3 with Pillow, the JieLi toolchain and three files of the JieLi AC79 SDK:

pip3 install Pillow mido python-rtmidi
tools/get_toolchain.sh                           # JieLi's clang for the chip, to ~/.jieli/toolchain
git clone --depth 1 --branch AC79NN_SDK_V1.2.1_2023-12-13 \
    https://gitee.com/Jieli-Tech/fw-AC79_AIoT_SDK.git ~/fw-AC79_AIoT_SDK

tests/run_host.sh runs the same firmware on your computer, writing the sound to a WAV and the screen to images.

If something goes wrong: hold OCT- while switching on to reach the USB rescue mode (no sound, only the updater), and install a working build from there. If the firmware crashes twice at boot, the FM-1 goes there by itself.

For developers

The whole synth is in firmware/src/dinghy.c. Everything underneath it (boot, USB, updates, the audio interrupt, settings) is Dinghy's platform: see docs/API.md for what it offers and docs/RULES.md for the chip's rules (no FPU, no 64-bit division, the audio time budget), which the build checks for you.

License and credits

GPL-3.0-only: you may change and share it, and whoever gets a firmware built from it gets its source too. Details and third-party parts in LICENSING.md.

  • FMLarynx (the formant synth, sequencer, screen and effects in dinghy.c): Presethead
  • The formant filter design follows MouthTowel by nickb808-dev
  • Dinghy (the app skeleton, the wiring platform.c, host mode, docs): zvenson
  • The platform: Copyright (C) 2026 Leo Kuroshita (@kurogedelic), Hügelton Instruments (Felucca), with the changes of SLOOP (isod89)

"M-VAVE" and "FM-1" belong to their owners. FMLarynx is not made or endorsed by them.