What it does
A voice goes in on J1. What comes out on J9 and J10 is that voice corrected to a key and scale, at a speed from transparent to robot, with up to four harmony voices that walk the scale from whatever note you sing, a stereo doubler, and a formant control that changes the size of the singer without changing the pitch.
Seven voices from one listen
The engine finds your pitch once per 5 ms and lays down a train of pitch marks. Every output voice reads the same marks and re-fires them at its own spacing, so four harmonies and a doubler cost little more than one.
A tuner in the panel
The ring around the KEY pot shows the scale's notes as dim dots and the note you are singing as a bright one: green within a quarter tone of a scale note, orange outside it. Thirteen LEDs beat four.
HARD, and the harmonies
Hold B1 and correction goes instant and total, the robot. Tap it and that latches. Tap B2 to mute the harmony voices; hold it 0.6 s for HOLD, which keeps them on their notes while you sing on. A gate on J3 punches HARD from a sequencer.
It is the same C engine as Belt for the Ableton Move, recompiled for the Alchemy Lab: six pots on two pages, three settings knobs, three buttons, six CV jacks that read independently of the pots, and 102 LEDs. Fixed latency of 24 milliseconds, with the dry path delayed to match so the wet and dry stay in phase. It also brings firmware swapping from the SD card, so this module can carry several firmwares and change between them from a settings page.
The panel
Every hole sits where it sits on an Alchemy Lab. The coordinates come from the SDK's own KiCad front-panel template, not from a photo, and the drawing is generated from them. The PLAY page is what you reach for while singing; the SETUP page, the four voices, appears while B3 is held.
Turn a knob or press a button to see what it does.
The panel
Singing through it
1 Bring a voice up to line level and patch it to J1. J2 too if you have it; the engine listens to the two summed and keeps the dry path stereo. 2 Set KEY and SCALE. The ring around KEY lights the scale's notes; sing, and your note appears on it, green when you are on one. 3 RETUNE is the speed. 0 is the robot. Start around a quarter of the way up. 4 Hold B3. P1 and P2 are the first two voices' intervals: a third and a fifth above out of the box. Let go. 5 Bring up HARMONY. Sing a scale.
Hold B1 for HARD: correction instant and total, whatever RETUNE and AMOUNT say, for as long as you hold. Tap B1 to latch it; tap again to release. The B1 light goes white while HARD is on and is the tuner's colour otherwise. B2 is the harmonies' button: tap to latch the mute; hold it 0.6 s for HOLD, the voices kept on their notes. Both buttons stand down while B3 is held, so reaching for Settings never fires either.
FORMANT resizes the singer without moving the pitch: left is bigger, right is smaller, the centre is you. Half an octave each way. AMOUNT is how far towards the scale note the correction goes; at 100 it lands on it. The three engine parameters that did not fit the panel, FLEX, HUMANIZE and WET, are knobs in the Settings pages, and they are the ones to reach for if it sounds too corrected: FLEX leaves singing that is far from any scale note alone, HUMANIZE keeps your vibrato through the correction and gives each harmony voice a slow wander of its own.
What it needs from the signal
A single voice, at line level, reasonably clean. The pitch finder tracks one fundamental between about 92 Hz and 1 kHz, low F2 to high B5, and gates on level: below about −56 dBFS the voices duck and the correction holds its last offset, so breaths and room do not get a harmony. A chord in, or a voice with a loud reverb already on it, gives it two pitches to choose from and it will pick one.
The lowest trackable note is a few hertz higher than on the Move, a consequence of running the same analysis window at 48 kHz instead of 44.1; the latency is two milliseconds shorter for the same reason.
What the voices sing
A harmony voice does not add a fixed interval. It takes your corrected note, finds its degree in the scale, and walks that many degrees up or down the scale, so a third above C in C major is E, and a third above D is F. This is the engine's own arithmetic on the page: pick a key, a scale and four intervals, then drag the note you are singing.
Chromatic is the exception: with no scale to walk, the intervals become fixed semitones, a third is four of them, a fifth seven. Octaves are always twelve semitones, whatever the scale. Unison is a voice on your own note, which with HUMANIZE up and SPREAD wide is a second singer. The engine's targets carry half of your vibrato; the doubler is a pair of streams ten cents either side of the corrected lead, panned hard.
Each voice also has a static detune of a few cents and a slow random wander, both scaled by HUMANIZE, so four voices do not sound like one singer copied. With HUMANIZE at zero they lock to the grid and sound like a keyboard, which is sometimes what you want.
The second page, and the settings
Belt has sixteen parameters and the panel has six pots. The four voices and the doubler live on the SETUP page, held on B3; the three you set once and leave, FLEX, HUMANIZE and WET, are knobs in the Settings pages.
SETUP — hold B3
| Pot | Parameter | Range | Ring |
|---|---|---|---|
| P1 | VOICE 1 interval | Off · −Oct · −6th · −5th · −4th · −3rd · Unison · +3rd · +4th · +5th · +6th · +Oct | 12 dots |
| P2 | VOICE 2 interval | 12 dots | |
| P3 | VOICE 3 interval | 12 dots | |
| P4 | VOICE 4 interval | 12 dots | |
| P5 | DOUBLER, a pair of detuned copies of the corrected lead, panned wide | 0–100% | level |
| P6 | SPREAD, how wide the harmony voices sit in the stereo field | 0–100% | level |
Opening the page to look cannot change anything. The SDK's pot catch runs on the way in and on the way out: a SETUP pot only takes effect once you turn it through the value it already holds, and letting go of B3 hands the pots back to the PLAY page without jumping anything. Both pages, SETUP and PLAY, are saved to flash five seconds after you stop moving them, with hands off the buttons, and come back at the next power-up.
At boot the PLAY page keeps its saved values, and the pots catch them. The six pots are shared by every firmware on the card, so after a switch in the picker they point wherever the last firmware left them; adopting them would overwrite Belt's settings with Mark's or Smack's. So a pot does nothing until you turn it through the value Belt saved, then takes over. Only the first boot after flashing, with nothing saved, adopts the pots as they sit.
First boot after flashing seeds the SETUP page with a third and a fifth above, the other two voices off, no doubler, spread 70%.
Settings — hold B2 + B3 for two seconds
Brightness · flex · presets · humanize · wet
P1 ring brightness. P2 FLEX: how far from any scale note the singing may stray before correction lets go of it; 0 corrects everything. P3 / P4 preset slot and action, sixteen slots. P5 HUMANIZE: vibrato kept through the correction, and the voices' wander. P6 WET: corrected lead against the dry voice; the harmonies and doubler add on top either way. Out of the box: FLEX 0, HUMANIZE 30%, WET 100%.
Firmware · USB port
The SD card picker: P1 file, P2 flash, P3 DFU. The card section is about it. P6 USB PORT: Mac, Launchpad or Audio, below.
Chord
What held notes do: P1 MIDI NOTES, P2 LEAD, P3 HOLD (Freeze or Lock), P4 J8 (Formant or Hold gate), P5 VEL SENS, P6 OCTAVE. The chords section has the details.
Sources
Where else held notes come from: P1 CHORDS FROM, P2 J3, P3 TEMPO, P4 triads or sevenths, P5 CV CAL, P6 CV INS. Below.
Settings pages at a glance
| Page · pot | Control | Choices, range, default |
|---|---|---|
| 1 · P1 | BRIGHTNESS | 5–100% · default 30% · changes as you turn |
| 1 · P2 | FLEX | 0–100 · default 0 |
| 1 · P3 | PRESET SLOT | 16 slots, 0–15 · picks the slot for P4 |
| 1 · P4 | PRESET ACTION | fully left: save · fully right: load · hold 3 s |
| 1 · P5 | HUMANIZE | 0–100% · default 30% |
| 1 · P6 | WET | 0–100% · default 100% |
| 2 · Firmware · P1 | FILE | the .bin files in /alchemy · up to 16 |
| 2 · Firmware · P2 | FLASH | dip below ~85 %, then past ~95 % · writes and reboots |
| 2 · Firmware · P3 | DFU | dip below ~85 %, then past ~95 % · reboots to the bootloader |
| 2 · Firmware · P4 | — | nothing |
| 2 · Firmware · P5 | — | nothing |
| 2 · Firmware · P6 | USB PORT | Mac · Launchpad · Audio · default Mac |
| 3 · Chord · P1 | MIDI NOTES | Off · Harmony · Target · default Harmony |
| 3 · Chord · P2 | LEAD | 0–100 · default 100 · 0 = chord only |
| 3 · Chord · P3 | HOLD | Freeze · Lock · default Freeze |
| 3 · Chord · P4 | J8 | Formant · Hold gate · default Formant |
| 3 · Chord · P5 | VEL SENS | 0–100 · default 50 |
| 3 · Chord · P6 | OCTAVE | C2 · C3 · C4 · C5 · default C3 · as you turn |
| 4 · Sources · P1 | CHORDS FROM | Pads · Seq · CV · MIDI · default Pads · as you turn |
| 4 · Sources · P2 | J3 | Hard gate · Chord clock · default Hard gate · as you turn |
| 4 · Sources · P3 | TEMPO | 40–240 BPM · default 120 · as you turn |
| 4 · Sources · P4 | CHORD | Triads · Sevenths · default Triads · as you turn |
| 4 · Sources · P5 | CV CAL | Off · On · Learn · default On · as you turn |
| 4 · Sources · P6 | CV INS | Chord · J4 · J4–J5 · J4–J6 · J4–J7 · default Chord · as you turn |
B1 steps to the next page when you let go of it and is lit orange while
Settings is open; a press of B2 or B3 leaves. FLEX, HUMANIZE and WET apply when Settings closes, and so do the Chord page's P1 to P5; BRIGHTNESS, OCTAVE and the whole Sources page as you turn (the chord sources keep running while Settings is open); USB PORT at the next power-up. Every Settings value except the picker's
three is saved in Belt's preset slot 14 about five seconds after Settings closes; USB PORT is also
written to /alchemy/usb.cfg on the card, shared by every firmware on it. The
panel drawing has all four pages: pick Settings 1 to Settings 4 above it and
tap any pot, button or jack.
Leaving Settings counts as a change: brightness, FLEX, HUMANIZE and WET are saved with the pages five seconds later. The USB port setting goes to the card the moment Settings closes. On module 2 the Settings chord opens, but more slowly with audio patched than in Mark; the likely reason, not yet measured, is the seven voices leaving the control loop less time.
What it remembers
Belt keeps its working state, both pages, the Settings knobs and the last session's CPU readings, in preset slot 14, counting from zero (15 in HostLink's list). Each firmware in the family has a slot of its own: Smack 12, Mark 13, Belt 14, Relay 15. Picking Mark in the picker and coming back later finds Belt as you left it. Slots 0 to 11 are for presets saved by hand; saving one by hand into 12 to 15 overwrites that firmware's working state.
Builds before this one autosaved into slot 0. At boot Belt still reads slot 0 once, if it holds Belt's own settings (the schema guard refuses any other firmware's), so a module carries its settings over; once slot 14 holds anything, it wins. Switching away and back has been confirmed on the hardware in Mark and Smack; Belt's own round trip, and a cold power-cycle, are next on the test list.
The chords-all build (beta) also keeps the chord sequencer's progression and the
CV inputs' learned offsets in slot 14. Its Settings pages and saved extras are a new shape, so
its first power-up starts from Belt's first-boot defaults, once. HOLD, and which
Launchpad page is up, are never saved.
Reading the rings
The SDK draws every pot's value on its ring in the colour of the page you are on. On top of that the firmware adds the tuner, three button lights and a report at boot.
| Where | Shows |
|---|---|
| KEY ring | The SDK's 12-zone selector, one dot per key with the chosen one bright, plus the tuner: the scale's other notes as dim dots, and the note you are singing as a green pip within 25 cents of its target or an orange one outside. The pip sits on the dot the pot would select for that note. |
| Other rings | A bar for continuous pots, one dot per step for stepped ones, two arms from a white pivot for FORMANT. SETUP colours appear while B3 is held. |
| B1 · HARD / tuner | white while HARD is on · else green in tune · orange off it · dim blue when nothing voiced is coming in |
| B2 · HARMONIES | purple while any voice has an interval and is not muted · grey muted · dim when no voice is on · blue while HOLD is on, dim if also muted · red = the audio callback's average load is above 80% |
| B3 · SETUP | A dim violet tint while the PLAY page is up; the SDK lights it in the page colour while SETUP is held. For three seconds after a CV calibration, the result: green, amber or red. |
| P1 ring, first 2.5 s | Last session's worst CPU load, as a bar. See below. |
| All three buttons red | The engine could not allocate its buffers. It needs 137 KB of a 1 MB pool, so this should be impossible; it fails loudly rather than running silently broken. |
The boot report
Seven pitch-shifting voices on a 480 MHz Cortex-M7 was the open question. You cannot watch a status light while singing, so the module measures its own worst-case load and shows it on the P1 ring for the first two and a half seconds of the next power-up.
A single dim blue LED means it has not measured anything yet. Green is under 75%, amber under 90%, red means it did not fit.
What the rack said. The first build on module 2 recorded a 100% worst block, and the control loop starved: the Settings chord stopped opening reliably. Two of the three known fallbacks fixed it. The engine is now compiled with faster float maths (its own file only; the SDK and libDaisy keep strict arithmetic), and its buffers moved from the external SDRAM into 160 KB of internal D2 SRAM, because seven voices reading the pitch-mark rings at scattered offsets every sample were waiting on SDRAM. The worst average load since is 63.7%, with no red on B2 and no clicks. The third fallback, fewer voices on by default, has not been needed. The worst single block, what this ring shows, has not been written down since the fix; the average is read over HostLink.
Every knob under CV
The Alchemy Lab reads pots and jacks separately and the SDK adds them in software, per page and per pot. Five jacks modulate the PLAY page; the sixth is a gate.
| Jack | Drives | Page |
|---|---|---|
| J3 | HARD gate — high is HARD, as if B1 were held; or the chord clock | — |
| J4 | KEY, twelve zones across the CV range; not volt per octave. Or the CV chord's root, or pitch 1 | PLAY P1 |
| J5 | RETUNE, or chord pitch 2 | PLAY P3 |
| J6 | AMOUNT, or chord pitch 3 | PLAY P4 |
| J7 | HARMONY level, or chord pitch 4 | PLAY P5 |
| J8 | FORMANT, or the HOLD gate | PLAY P6 |
A slow LFO into J8 is the obvious first patch: the singer's size breathing while the pitch stays put. A sequencer into J3 makes HARD rhythmic. J4 steps the key from a sequencer, which changes what every harmony voice sings on the spot.
J3 is read raw in the audio callback, not through the SDK's 20 Hz pot filter, which would round a gate's edges into a swell. It fires on the magnitude of the swing away from the jack's calibrated zero, 1.5 V to assert and 0.5 V to release, so a gate counts whichever way the front end signs it. On module 2 a clock into J3 flashes B1 white in time; at fast rates the light stops matching, because the LEDs redraw at about 60 Hz while J3 is read every 2.7 ms, one 128-sample block. A pulse shorter than a block can fall between two reads, so give it 5 ms or more.
J4 to J8 have not been tried on the hardware yet. The mapping above is what the source sets up.
The alternatives in the table are Settings choices: J4 to J7 become volt-per-octave chord pitches with Chords from = CV, J3 the chord clock, J8 the HOLD gate. They are beta, in the chords section.
Chords: Hide and Seek, HOLD and chord sources
Out of the box the four harmony voices walk the scale from what you sing. They can also sing notes you hold: on the Launchpad, on a USB keyboard, from Belt's own chord sequencer, from CV on J4 to J7, or from another Lab over the rear header. Every one of those becomes the same held-note message to the engine, so they all behave alike. And HOLD keeps the voices on the notes they are on while you sing on.
Beta: built and tested on a Mac, not yet on a module
Everything in this section is in the chords-all build. It passes its native
tests and the full-firmware emulator, including a link test fed the exact bytes
seq-alchemy's chord output sends. None of it has run on an Alchemy Lab yet. That covers
J4 to J7 as pitch inputs, the rear-header MIDI link, USB keyboards on the real host, and how
much of the processor the extra work takes on a module that already runs at about 64%.
The first power-up after installing this build resets Belt's saved settings once. The Settings pages and the saved extras changed shape, and the schema guard refuses the old slot, so Belt starts from its first-boot defaults: a third and a fifth above, the pots adopted as they sit.
Hide and Seek in 30 seconds
1 Hold B2 + B3 two seconds for Settings. Tap B1 to step to page 3, Chord. P1 MIDI NOTES stays on Harmony, the default. Turn P2 LEAD to 0. Press B3 to leave. 2 Hold B3 and turn P1 and P2, VOICE 1 and 2, fully left to Off (3 and 4 are off already). 3 Hold a chord: the Launchpad's PLAY page (top button 3), a USB keyboard, or Settings page 4 Chords from = Seq for Belt's own progression. 4 Sing. Each held note is your voice moved to that pitch, up to four at once.
It is a harmonizer, not a filter-bank vocoder: the engine finds your pitch and re-pitches your own voice, keeping its formants, which is why the words stay clear. LEAD at 0 takes out the corrected lead, the dry voice and the doubler together, so only the held notes sound. With LEAD up, the chord sits under your lead.
What a held note does
| Pot | Control | Choices, default | Does |
|---|---|---|---|
| P1 | MIDI NOTES | Off · Harmony · Target · default Harmony | Harmony: each held note takes a harmony voice, up to four; a fifth note steals the voice of the oldest one. Target: the newest held note becomes the pitch the lead is corrected to, so you play the melody and sing roughly. Off: held notes are ignored. |
| P2 | LEAD | 0–100 · default 100 | The corrected lead, the dry voice and the doubler together. 0 is chord only. |
| P3 | HOLD | Freeze · Lock · default Freeze | What HOLD does, below. |
| P4 | J8 | Formant · Hold gate · default Formant | J8 is FORMANT's CV, or a gate that holds while high. |
| P5 | VEL SENS | 0–100 · default 50 | How much a note's velocity sets its voice's level. The Launchpad, the sequencer and CV chords all send 100; a keyboard and rear-header MIDI send what they play. |
| P6 | OCTAVE | C2 · C3 · C4 · C5 · default C3 | Where the sequencer's chords sit (their roots start at this C) and what 0 V means on a CV chord input. Keep the chord near your voice: the further a voice is moved, the less it sounds like you. |
Notes 0, 1 and 2 are the engine's control notes (momentary HARD, doubler and harmony mute), not pitches; a USB keyboard's are skipped for that reason. A release always goes through, even with Settings open, so a note cannot stick because Settings was up when you let go.
HOLD
A pad that outlasts you
The voices keep the chord you were singing and sustain it as a pad, even through silence: they play from the last stretch of voiced singing, so a HOLD caught in a breath freezes the note just sung. What you sing next does not move them. Letting go fades out over about a third of a second, then the voices follow you again.
Your words on a fixed chord
The voices keep their notes but sing with your live voice, so the words come through on the held chord, and they go quiet when you do, like harmonies always do.
| Turn HOLD on or off with | Gesture |
|---|---|
| B2 | Hold 0.6 s. It toggles at 0.6 s, while you are still holding, and the release does nothing. A tap shorter than that still latches the harmony mute. |
| Launchpad top 4 | Press to toggle. |
| Launch Control XL upper button 3 | Press to toggle. |
| Haute42 L3 | Press to toggle (it no longer plays Stutter 1/2). |
| J8, with the Chord page's J8 on Hold gate | Held while the gate is high. It reads the size of the swing away from 0 V, with a gap between on and off, so a gate of either polarity counts. |
HOLD is on while the latch or the J8 gate is. B2 is blue while HOLD is on (dim blue if the harmonies are also muted), the Launchpad's harmony-voice pads turn blue, top 4 is bright blue, the XL's upper button 3 bright green. HOLD is never saved: a power-up always starts with the voices following you. B2 no longer mutes while it is held, because the 0.6 s of silence before a HOLD would drop the very voices being held; the Launchpad and XL MUTE buttons keep their hold-to-mute.
The Launchpad's PLAY page
In PLAY, rows 1 to 6 are three octaves of keyboard, two rows each with the sharps above the naturals as on the KEY page: rows 1–2 are C5 to B5, rows 3–4 C4 to B4, rows 5–6 C3 to B3. Every pad held is a held note at velocity 100 (the Mini MK3 has no velocity). Held pads are green, the key's root blue, in-scale notes dim blue. Rows 7 and 8 stay the harmony voices and the tuner. Leaving PLAY lets go of every held pad. Top 3 is dim green in KEY and bright in PLAY. Every power-up starts in KEY.
Where else held notes come from
The Launchpad's PLAY pads and a USB keyboard always play. On top of them, one more source at a time, chosen on the last Settings page. Changing it lets go of every note the old source held, and only those.
| Pot | Control | Choices, default | Does |
|---|---|---|---|
| P1 | CHORDS FROM | Pads · Seq · CV · MIDI · default Pads | Pads: nothing more than the hands. Seq: Belt's chord sequencer. CV: chord pitches on J4 to J7. MIDI: notes from another Lab on the rear header. |
| P2 | J3 | Hard gate · Chord clock · default Hard gate | Chord clock: each rising edge on J3 moves the sequencer to its next chord, or reads the CV chord (sample and hold). HARD is then B1 and the controllers' HARD buttons only. |
| P3 | TEMPO | 40–240 BPM · default 120 | The sequencer's tempo. A chord lasts its bars of 4/4. |
| P4 | CHORD | Triads · Sevenths · default Triads | Three notes, or four: one for every harmony voice. For the sequencer and for CV in Chord mode. |
| P5 | CV CAL | Off · On · Learn · default On | The CV inputs' learned offsets: applied, ignored, or learned now. See CV chords. |
| P6 | CV INS | Chord · J4 · J4–J5 · J4–J6 · J4–J7 · default Chord | Chord: J4 alone, its voltage the chord's root, the chord built from KEY and SCALE. J4 … J4–J7: a note per jack. The jacks not used keep modulating their knobs. |
Belt's own chord progression
The progression engine of the Alchemy Lab sequencer (seq-alchemy), the same code, playing up to eight chords, each one to eight bars, at TEMPO. The chords are built in Belt's KEY and SCALE: a chord on a scale degree stacks every other note of the scale above it, three or four of them. Seq has no Chromatic or Blues, so Chromatic builds Major's chords and Blues builds Minor pentatonic's. Out of the box: i, VI, III, VII, a bar each, which in A minor is Am, F, C, G. Edit it on the Launchpad's CHORDS page, below.
One edge, one chord
Each rising edge on J3 moves to the next chord, whatever the tempo; the bars are not used. A trigger or gate from a sequencer's chord-change output is the idea. J3 is read once per audio block, every 2.7 ms, so give it a pulse of 5 ms or more. A held-high gate is one edge, not many.
The Launchpad's CHORDS page
| Pad | Does | Colour |
|---|---|---|
| Columns 1–8 | Chords 1 to 8 of the progression, left to right. | — |
| Rows 1–7 | The chord's scale degree: VII on row 1 at the top, down to I on row 7. Press to set it. Pressing in a column past the end lengthens the progression to that column. | cyan: the chord's degree · green: the chord playing now · grey: a column past the end, kept for later |
| Row 8 | The chord's length: press to step 1 → 2 → 4 → 8 bars → 1. | dim amber 1 · amber 2 · orange 4 · red 8 |
| Right column 1 | Run / stop. Stopped, the voices let go of the chord; running again starts from chord 1. | green running · dim green stopped |
| Right column 2 / 3 | One chord fewer / one more. | grey |
| Top 5 | CHORDS on and off: off goes back to KEY. Top 3 leaves it for PLAY. | magenta in CHORDS · dim magenta |
The playing chord is shown only while Chords from is Seq. The progression is saved with Belt's slot; key and scale come from the panel, triads or sevenths and the tempo from the Sources page. Changes are heard at once: the voices on notes the old and new chord share are left alone, and only the notes that change move.
CV chords
With Chords from on CV, Sources P6 CV INS chooses how the jacks are read. 0 V is the Octave's C (C3 out of the box) and each volt an octave up, either way.
One jack, one chord
J4's voltage is the chord's root. It is snapped to the nearest note of KEY and SCALE, and the chord built on that scale degree is held: triads or sevenths, as Sources P4 says. The quality falls out of the scale. In C major, 0 V is C, then Dm, Em, F, G, Am and B diminished up to 11/12 V; in A minor, 9/12 V is Am and 0 V is C. Chromatic builds Major's chords, Blues Minor pentatonic's, as for the sequencer. J5 to J7 keep modulating RETUNE, AMOUNT and HARMONY.
A note per jack
Each jack in use is one note, rounded to the nearest semitone, not to the scale: the sender decides the chord. Those jacks stop modulating KEY, RETUNE, AMOUNT and HARMONY while they carry it. An unpatched jack reads 0 V, which is a note (the Octave's C), so choose only the jacks you patch.
A chord changes only once the voltage has clearly left the one it is on and stayed away 3 ms. In Chord mode that means another scale note is nearer than the held one by more than about 25 mV; per jack, the jack has gone more than half a semitone plus a little, about 54 mV. So a voltage parked on a boundary does not flicker, and a jump lands once, not on every step on the way. A change of KEY or SCALE re-snaps the chord at once. With J3 on Chord clock the jacks are read only on a J3 edge: sample and hold.
Calibration
Rounding leaves little room, ±41.7 mV to a semitone, and an Alchemy Lab's J3 to J6 are rated about ±50 mV as outputs. So the sending module's error is learned once, per input, and taken off. What the sender plays while you learn depends on the mode:
| CV INS | The sender plays | Learned |
|---|---|---|
| Chord | J4 at 0 V | J4 only; J5 to J7 are carrying their knobs' CV and are left alone |
| J4 … J4–J7 | J4 0 V · J5 +4/12 V (0.333) · J6 +7/12 V (0.583) · J7 +1 V | All four: C, E, G and C an octave up |
With the reference coming in, open Settings, page 4, and turn CV CAL to Learn. A quarter of a second later each input's offset, what it reads minus what it should, is stored in Belt's slot. Turn it back to On and leave Settings: for three seconds B3 shows the result, green every input the mode learns, amber some, red none. An input more than 0.25 V off is taken for a wrong patch, not an error, and keeps its old offset, so in the four-jack modes learn with all four patched. Only a turn into Learn learns; a slot saved with Learn showing does not relearn at power-up. Off reads the jacks raw.
Two Labs: MIDI over the rear header
The rear header carries −12 V, +12 V and 3V3A. Never use a straight ribbon.
A 1:1 ribbon would join TX to TX and put the power rails of both modules on each other's signal pins. Wire the link by hand, signal and grounds only. Hermetic's own words for the header: develop at your own risk.
| From the sending Lab | To Belt's Lab | What |
|---|---|---|
| Pin 8 (B3, PB6, USART1 TX) | Pin 7 (B5, PB7, USART1 RX) | The MIDI, 31,250 baud |
| GND: several or all of 2, 5, 12–14, 16–19 | GND: the same | Grounds |
| Nothing else. Leave 1, 11 and 15 (−12 V, +12 V, 3V3A) and 10 and 20 (the module's own I²C bus) unconnected. | ||
Pin numbers are the positions on the SDK's header drawing. With Chords from on MIDI, Belt holds the notes that arrive, on any channel; a note-on at velocity 0 counts as a note-off. MIDI clock, start and stop are read and ignored. Belt only listens: its UART runs receive-only with no transmit pin, so Belt never drives its own pin 8, and a cable crossed both ways still works. The bytes are read in the control loop, not in the interrupt. With any other source, rear-header MIDI is read and dropped.
The sender is the Alchemy Lab sequencer (seq-alchemy) with its Chord out setting on MIDI or MIDI + clock: it sends the chord playing as three or four notes around middle C, the notes that leave switched off before the new ones come on, and shared notes left held. That exact byte stream, C, Am, F, G and a stop, has been run through Belt's receiver and engine on the Mac: Belt held the sender's notes every millisecond, and nothing after the stop.
USB-MIDI keyboards
With the USB port in Launchpad mode, a USB-MIDI device that is not a Launchpad Mini MK3 or a Launch Control XL is taken as a keyboard: any class-compliant one, an Arturia KeyStep 32 for instance, no set-up. Its notes are held notes, as on the PLAY pads, and its sustain pedal holds them; every channel and cable is merged. It plays with whatever Chords from says. Key presses are ignored while Settings is open; releases and the pedal never are.
Through the powered hub dongle
The front port has no 5 V, so a keyboard goes into the same powered hub dongle as the other controllers; up to four devices behind it. Plugged straight in, through a passive 5 V injector, only a keyboard whose first USB interface is an audio one, with its MIDI interface right after, is served (most are). If B2 goes red that way, use the hub.
Notes let go by themselves
Pull a keyboard out mid-chord and its notes and pedal are released: straight away when it was plugged straight in, within half a second when it was behind the hub, which checks one of its ports every tenth of a second. Plug it back in and it plays again. The same goes for a Launchpad's held pads and a gamepad's held buttons. B2 is white while a key is held.
If the host does not come up, the /lpdiag.txt report on
the card has a keys: line: which slots are keyboards, their USB IDs, how many notes
each holds, and the notes received and dropped since power-up.
Firmware on the card
Hermetic's firmware treats the SD card as a place for presets and files. This one
also reads .bin files from it, and can write one into the module's firmware slot,
verify it, and reboot into it, from a settings page, with the module on and in the rack. Smack
and Mark for the Alchemy Lab carry the same page, so any of the three can hand the module to
any other.
FAT32, a folder named alchemy
32 GB or under, MBR partition table, FAT32. Make a folder called alchemy in
the root and put firmware images in it: any .bin built for the Alchemy Lab
bootloader, this one included. On a Mac, run dot_clean on the card before
ejecting so the picker does not list resource forks as files.
Without pulling the card
Files reach the card over USB while the module runs: the web programmer's file panel,
or the repository's tools/hostlink-fs.mjs, which makes the folder and puts
the images in it from a terminal. Uploads are staged and renamed onto their final name
only after the firmware has checked the CRC.
The gesture
| Pot | Does | Ring |
|---|---|---|
| P1 · FILE | Picks a file. One dot per .bin in the folder, the chosen one bright; turn to move the choice. |
green dots · red: no card · orange: no folder, or no files |
| P2 · FLASH | Writes the chosen file. Turn it down below 85%, then all the way up. The dip arms it, so a pot that happens to be parked at maximum cannot fire on entry. It first compares the file with the firmware already in the slot: pick the firmware that is running and nothing is erased, written or rebooted, so nothing you are playing is interrupted. The ring goes solid green; turn the pot back down and the list returns. | teal comparing · solid green: already running, nothing done · orange erasing · blue writing · green verifying · white, then reboot · blinking red: failed, nothing booted; turn down to try again |
| P3 · DFU | Same gesture. Reboots into the bootloader's update mode and stays there for a USB flash: the escape hatch for a firmware that has no picker of its own. | violet arming bar |
What it refuses, and what it never touches
It checks the image's first eight bytes before erasing anything and refuses one that is not bootable from SRAM. The largest file it will take is the app slot up to the calibration sector, so the board's calibration record and the preset store are never in the erase path. If a write fails, the module blinks red and boots nothing; the bootloader is intact, and hold-B3-at-power-on still gets you a USB flash.
What has run. On module 2 (22 September 2026) the picker switched the module between Belt, Mark and Smack, and picking the firmware already running changed nothing, as above. The card side was proven earlier in Smack: a card in the module written and read back byte-identical over USB, through the mount and buffers the picker uses.
USB and controllers
The front USB-C does one thing per power-up. By default it talks to the Mac: the web programmer, presets, the card. Switched over, the Lab becomes the USB host for a Launchpad Mini MK3, a Launch Control XL, a Haute42 gamepad and USB-MIDI keyboards, or a two-in, two-out USB audio interface.
The USB port setting
Hold B2 + B3 for two seconds to open Settings, tap B1 to the Firmware page, and turn P6, the bottom-right pot of Settings page 2, the Firmware page, next to the picker. It is a three-way selector:
| Mode | The front USB-C is |
|---|---|
| Mac | HostLink, the default: the web programmer, presets and the card's files, with the module racked. |
| Launchpad | The USB host for controllers. The Lab drives a Launchpad Mini MK3, a Launch Control XL and a Haute42, through a powered dongle; see below. No HostLink this boot. |
| Audio | A class-compliant USB audio interface (USB Audio Class 1): 2 channels in from J1/J2, 2 out to J9/J10, 48 kHz, 24-bit, no driver needed on a Mac. Belt's engine is bypassed: what the computer plays comes out of J9/J10, what comes in on J1/J2 goes to the computer. There is no volume control in the path and J9/J10 are DC-coupled, so a DAW can send CV through them. No HostLink and no controllers this boot. |
One setting for the whole card, from the next power-up
The mode is kept on the SD card in /alchemy/usb.cfg, shared by every firmware on it: each one adopts
the card's value at boot and writes a change back, so switching firmware in the picker keeps the mode. A change
takes effect the next time the module powers up.
Hold B1 while powering up for Mac mode for that one boot, whatever the setting says: the way back to the web programmer without opening Settings. The port has one USB role at a time, so Audio mode means no controllers, and neither Launchpad nor Audio mode has HostLink. The bootloader's DFU (hold B3 at power-on) is unaffected.
What B2 says about the port
The host starting up
| dim purple | The first two seconds after power-up, before the host starts. |
| blue | Starting the USB host. |
| cyan | Host running, nothing on the wire: no dongle seen. |
| yellow | A device is attached and enumerating, or the dongle's hub is up with no controller behind it yet. |
| red | The host gave up: an abort, an unsupported device, an error. |
| its usual colour | A controller is up: B2 goes back to its HARMONIES job. |
| white | While any Haute42 button, or any key of a USB keyboard, is held. |
The interface
| dim purple | Not started yet. |
| cyan | Waiting for a computer. |
| yellow | Connected, no stream open. |
| green | Streaming, at least one direction. |
If the host does not come up, a report of what it saw is written to the card as
/lpdiag.txt about 17 seconds after power-up, for reading back in Mac mode.
Hooking up controllers
The front port has no 5 V
The Lab's USB-C gives no bus power, so a controller needs it from somewhere else: a powered USB-C dongle with a USB hub inside. Power the dongle, plug it into the Lab's front USB-C, and plug the controllers into the dongle. The one it was developed with carries a hub and an Ethernet chip; a device that is not a controller, like the Ethernet chip, is switched off and skipped.
Four at once, one hub deep
Up to four devices at a time, full speed. Free ports are rescanned every half second, so a controller can go in after power-up. A device unplugged from the hub is noticed within half a second (each port is checked in turn every tenth of a second), what it held is let go, and plugging it back in brings it up again. The gamepad is only recognised behind a hub, never plugged straight in.
| Controller | USB ID | Set-up |
|---|---|---|
| Launchpad Mini MK3 | Novation 1235:0113 | None: the Lab puts it in Programmer mode and paints its pads. |
| Launch Control XL | Novation 1235:0061 | None: factory template 1 is selected automatically at connect, and again if the template is changed on the device. The MIDI channel is ignored. |
| Haute42 | 045E:028E | Must be in XInput mode (GP2040-CE), where it shows up as an Xbox 360 controller. |
| A USB-MIDI keyboard (beta) | any other class-compliant MIDI device | None. Its notes are held notes; see USB-MIDI keyboards. |
While Settings is open the controllers do nothing: the pads, buttons and knobs are ignored and any held effect lets go. Knobs and faders move the pages' stored values, so what they set is saved like a pot move, and the panel pot then has to catch the new value before it takes over again.
Launchpad Mini MK3
| Pad | Does | Colour |
|---|---|---|
| Rows 1–2 | KEY, laid out as a keyboard: sharps on row 1 (C# D# · F# G# A#), naturals on row 2 (C D E F G A B). Press a pad to set KEY. | bright blue: the key's root · dim blue: in the scale · grey: out of it · the note you are singing green within 25 cents, orange outside |
| Rows 4–5 | SCALE, nine pads: row 4 Chromatic · Major · Minor · Harm Minor · Dorian · Mixolydian · Maj Pent · Min Pent, row 5 pad 1 Blues. Press to set SCALE. | bright: the current scale · dim: the rest |
| Row 7, pads 1–4 | Harmony voices 1–4 (display only). | off: no interval · dim cyan: set · bright while you sing and the harmonies are not muted · blue while HOLD holds them |
| Row 8 | The tuner: where the sung note sits, flat to the left, sharp to the right, ±50 cents across the row. | green within 25 cents · orange outside |
| Top 1 | HARD tune: hold for momentary, tap to latch. The same gesture as B1, sharing its latch. | red on · dim red off |
| Top 2 | Harmony MUTE: hold for momentary, tap to latch. The same as B2, sharing its latch. | yellow muted · dim |
| Top 3 | KEY / PLAY: PLAY turns rows 1–6 into three octaves of held notes (beta, the chords section). | green in PLAY · dim green in KEY |
| Top 4 | HOLD on / off (beta). | blue on · dim blue |
| Top 5 | CHORDS: the chord sequencer's progression (beta, the chords section). | magenta on · dim magenta |
| Rows 3 and 6, top 6–8, right column | Unused (the right column is used on the CHORDS page). | off |
Launch Control XL
| Control | Does | LED |
|---|---|---|
| Faders 1–4 | RETUNE · AMOUNT · HARMONY · FORMANT (PLAY P3–P6). | — |
| Faders 5–6 | DOUBLER · SPREAD (SETUP P5–P6). | — |
| Top knobs 1–4 | VOICE 1–4 intervals (SETUP P1–P4). | green: the voice has an interval · dim green: off |
| Middle knobs 1–2 | 1 KEY · 2 SCALE (PLAY P1–P2). | dim amber |
| Upper button 1 | HARD: tap to latch, hold for momentary, as B1. | red on · dim red |
| Upper button 2 | MUTE: tap to latch, hold for momentary, as B2. | amber muted · dim amber |
| Upper button 3 | HOLD on / off (beta). | green on · dim green |
| Everything else | Unused, the lower button row included. | off |
Haute42
Hold a button and its effect plays; let go and it returns to dry. The last button pressed wins. Let it go while another is still held and that one takes over; with nothing held it is back to dry. The effects are a performance-effects stage on Belt's stereo output, after the voices. Belt has no tempo of its own, so the effects run at 120 BPM.
| Button | Where | Effect | What it does |
|---|---|---|---|
| X | right hand, top row, 1st | Stutter 1/4 | Repeats the quarter beat that starts at the moment of the press, for as long as you hold. |
| Y | right hand, top row, 2nd | Stutter 1/8 | The same, an eighth of a beat. |
| RB | right hand, top row, 3rd | Stutter 1/16 | The same, a sixteenth of a beat. |
| LB | right hand, top row, 4th | Buzz | A 1/64-beat repeat: the sound frozen into a buzz. |
| A | right hand, bottom row, 1st | Reverse | The last two beats, backwards, looping while held. |
| B | right hand, bottom row, 2nd | Tape Stop | Slows to a halt over one beat, then silence until you let go. |
| RT | right hand, bottom row, 3rd | Half Speed | An octave down at half speed, re-anchored every two beats. |
| LT | right hand, bottom row, 4th | Echo | A dotted-1/8 ping-pong echo, each side feeding the other. It keeps ringing after you let go: a dub throw. |
| Left | left hand, ring finger | Low-pass | A low-pass filter sweeping down over two beats. |
| Down | left hand, middle finger | High-pass | A high-pass filter sweeping up over two beats. |
| Right | left hand, index finger | Crush | Sample-rate and bit reduction. |
| Up | thumb | Gate | A 1/16 chop. |
| L3 | extra button | HOLD | Not an effect: toggles HOLD (beta). It played Stutter 1/2 before. |
| R3 | extra button | Drive | Waveshaper distortion. |
The stutters, reverse, tape stop and half speed play from a two-second record of the output that is always running, so they have something to work on the moment you press. Changes fade over about 1.5 ms, so a punch in or out does not click. The same stage and the same map are in Mark. They run in Launchpad mode only.
Button positions
The positions here follow the standard GP2040-CE hitbox mapping. If the controller's button mapping has been changed, the same effects follow the XInput button names (X, Y, RB, LB, A, B, RT, LT, the directions, L3, R3), not the physical positions. Start, Back and Guide do nothing.
Download it
For the Alchemy Lab V2 only. This is a beta: it has been heard on one module, and the CV inputs and a cold boot are still to be tried.
Download belt_alchemy.bin All releases and notes
- Install it through the front USB-C as below. To switch firmware from the card, also get Mark and Smack, and put all three
.binfiles in/alchemyon the microSD card. - Belt keeps its working state in preset slot 14. If you saved something in that slot with another firmware, it is overwritten the first time Belt saves. Move it to another slot first.
- Custom firmware: Hermetic Modular did not write or test it, so please report problems here with an issue, not to them.
To build it yourself instead (a few minutes with the ARM toolchain installed):
git clone --recurse-submodules cd belt-alchemy make libdaisy # once make # build/belt_alchemy.bin, ~341 KB make test # the engine on its allocation pool, and the 48 kHz tuner proof
Needs arm-none-eabi-gcc, make and
dfu-util. libDaisy has nested submodules, so the clone must be recursive or the
HAL is missing. make BENCH_USB=1 BUILD_DIR=build-bench builds a variant with
HostLink on the Daisy Seed's own micro-USB, for a module out of its case on a bench bootloader;
it is not the one to rack.
Installing
The Alchemy Lab's bootloader serves DFU on the front-panel USB-C, so the module stays in the rack. Once this firmware is on it, so does every update after.
Hold B3 at power-on
During the two-second boot window the rings run a warm-white comet. Hold B3 through it
and they switch to a slow breathe with the B3 lights on: update mode. Then flash the
.bin with Hermetic's web
programmer, or from the repository:
make program-dfu
Live
With Belt running, the module can be asked to reboot into update mode over HostLink and flashed in the same breath, no button held:
make program-live
Or put the new .bin on the card and use the
picker.
Same door
Flashing any Alchemy Lab firmware, Hermetic's own included, the same way returns the module to it. Presets in the slots survive; Belt's working state stays in slot 14, schema-guarded, so another firmware will not read it as its own.
Before you flash it
It is custom firmware. Hermetic Modular did not write it, did not test it and cannot support it, so please do not contact them about it. It has been heard on one module, its author's. If you run it, the things worth reporting are what the boot report reads after a few minutes of singing with all four voices on, whether the tuner pip lands on the note you sang, and whether CV on J4 to J8 does what the table says.
How it is built
The engine's C file was not touched. Everything below is the layer between it and the Alchemy SDK, and the handful of decisions that shaped that layer.
| Piece | What it is |
|---|---|
| The engine, at 48 kHz | Belt's engine, byte-identical to the Move build's, with one edit in its header: the sample rate, because libDaisy offers no 44.1 kHz. Left at 44.1 it would have read every note a semitone and a half flat and tuned the singer to a scale that much sharp. A native test holds the retarget: 440 Hz reads note 69.00. The engine's file is compiled with -ffast-math -fno-finite-math-only, a build flag and not a source edit; the rest of the firmware keeps strict IEEE arithmetic. |
| The analysis | YIN pitch detection on the input decimated to 24 kHz, every 256 samples, with a tracking mode that keeps the lag search near the last period. A three-point median kills octave blips. One analysis feeds every voice. |
| The voices | Time-domain pitch-synchronous overlap-add: two-period Hann grains fired at the target spacing into one stereo accumulator. Formant is the grain content resampled, independent of the spacing, so pitch and size are separate controls. |
| Two pages, one layer | The SDK's Pager makes SETUP a held layer on B3 with pot catch on the way in and out. Nothing on the PLAY page can jump because you looked at the other one. At boot a saved PLAY page is restored and the pots catch it, so a firmware switch never drags Belt's settings to where another firmware left the pots. |
| Working preset | Slot 14 (0-based) is Belt's live state: both pages, the Settings knobs and the CPU readings. Each firmware in the family has its own (Smack 12, Mark 13, Relay 15). It autosaves five seconds after the last change on either page or in Settings, with hands off the buttons and the picker idle, one 4 KB sector per save. Slot 0, where earlier builds saved, is read once at boot to carry old settings over. |
| The picker | Three Custom slots on a Settings page: a file scanner, a state machine that compares, then erases, writes and verifies one step per frame, and a DFU hand-off. The compare reads the running image through the memory-mapped flash, so picking the firmware already loaded stops there. Shared, by copy, with Smack and Mark. |
| Engine pool, in D2 SRAM | A bump allocator, so the engine's five callocs land in a pool with no engine edits. It started in external SDRAM; the callback overran there, so it moved to 160 KB of internal D2 SRAM (the engine takes 137,552 B), placed after the LED driver's DMA buffer, which must own the first 32 KB. |
| HostLink | Product "Belt", both pages, ten jacks, three buttons, a manual and the SD filesystem, over the front USB-C. |
| Budget | ~341 KB image (348,812 B). SRAM 71%, DTCM 72%, D2 pool 160 KB, SDRAM 1.2 MB. CPU: worst average 63.7% on module 2. |
Found something, or want it to do something it doesn't? Open an issue. A report from someone singing through it is worth more than anything measurable on a laptop.
Specifications
Alchemy Lab V2
Daisy Seed2 DFM: STM32H750 at 480 MHz, 64 MB SDRAM. 12 HP. Hermetic Modular's Alchemy SDK, beta.
48 kHz · 128 · 24 ms
Stereo in on J1/J2, summed to mono for analysis; stereo out on J9/J10; fixed 24 ms latency, dry path matched.
92 Hz – 1 kHz
The pitch tracker's range, low F2 to high B5. Twelve keys, nine scales.
1 + 4 + 2
The corrected lead, four harmony voices at scale intervals from an octave below to an octave above, and a stereo doubler.
6 × 2 · 3 · 6
Six pots on two pages, three Settings knobs, three buttons, five CV inputs and a gate, 102 LEDs.
16 slots + card
Sixteen preset slots in QSPI flash, slot 14 Belt's own working state; firmware images and files on a FAT32 microSD.
The rest of them
Belt started on the Ableton Move under Schwung. This is its second body, and one of three firmwares for this module that share the picker, the allocator and the shape of the code.