Custom firmware · Hermetic Modular Alchemy Lab V2 · mi-alchemy v0.2.0

Elementsfor Alchemy Lab

Bow it, blow it, strike it. Tune the object it resonates in.

Built and tested on a laptop, not yet heard

This firmware compiles, and its native test suite passes: the samples file round-trips byte for byte, all six sound cases render, and the string tunes within 5 cents. It has not been flashed onto a module or listened to. CPU load on the module, the pitch at 0 V and the input levels are unmeasured.

12 HP · 6 pots · 3 pages · 10 jacks · drawn at true scale

What it does

The idea

Mutable Instruments' Elements is a modal synthesis voice: three exciters (a bow, a breath of noise and a strike) set a virtual object ringing, and you decide what the object is made of. This is its DSP, unchanged, running at its native 32 kHz on the Alchemy Lab.

The exciters

Bow · blow · strike

Mix them on the Exciter page (hold B3). Each has a level, a timbre and, for blow and strike, a character: FLOW turns the breath from steady to sputtering, MALLET goes from a mallet through recorded samples to bouncing particles. CONTOUR is the envelope over all three.

The resonator

What it rings in

The Play page tunes it and shapes it: GEOMETRY from plates and bars through strings to bells, BRIGHTNESS, DAMPING, and POSITION, where on the object it is excited. MODEL on the Timbre page swaps the modal resonator for a string, a string ensemble, or Ominous.

The space

Mono to reverb, and frozen

SPACE (Timbre page, hold B2) opens the two outputs from mono to stereo into Elements' reverb. The last eighth of its travel freezes the reverb, which the original module only reached with CV.

Elements had 16 knobs, 3 sliders and 7 CV attenuverters. The Alchemy Lab has six pots, so they are spread over three pages that you reach by holding a button, and the pots catch their stored values before taking over. Hold B1 to play; a gate on J3 does the same. Patch audio into J1 or J2 and it replaces the blow or strike exciter.

The panel

Drawn at true scale · click any control

The coordinates come from the Alchemy SDK's KiCad front-panel template, and the drawing is generated from them. Rings show the first-boot values in the firmware's own colours.

Select a control

The panel

6 pots × 3 pages · 3 buttons · 10 jacks · 102 LEDs
Hover or click anything on the drawing, or tab to it. Switch pages above. Audio in and out, the front USB-C and the light rings are fixed Alchemy Lab hardware; everything else is what this firmware makes of them.
plate 60.96 × 128.5 mm · 12 HP
pot pitch 35 mm across, 28 mm down · rings 16 LEDs, 13 in the arc
source KiCad template, parsed
J1/J2 sit under the IN legend, J9/J10 under OUT. The six CV jacks between them are numbered here in reading order, which the template does not state: the numbers printed on your panel are the authority.

At a glance

Front view: [P1] B1 [P2] · [P3] B2 [P4] · [P5] B3 [P6]
PageP1P2P3P4P5P6
PlayCOARSEFINEGEOMETRYBRIGHTNESSDAMPINGPOSITION
Exciter · hold B3BOWBLOWSTRIKECONTOURFLOWMALLET
Timbre · hold B2BOW timbreBLOW timbreSTRIKE timbreSPACEMODELFM
SettingsBrightness·Preset slotSave / load··
Settings 2FILEFLASHDFU···

B2 is a page button here

In the other firmwares for this module B2 is a plain button and only B3 holds a page. Elements needs a third page, so holding B2 shows Timbre. Hold B2 and B3 together for two seconds and Settings still opens: the pager drops a layer when both are down. How that feels on the panel is one of the things to check on hardware.

Playing it

From power-up to a struck bell
  1. Patch J9 and J10 to your mixer. J9 is Elements' main output, J10 the aux; with SPACE up they are a stereo pair.

  2. Hold B1. On a first boot the voice is Elements' init sound: a struck modal resonator, STRIKE at 80%, a short CONTOUR, a little SPACE. B1 is momentary, so a tap is a short note.

  3. Tune it on the Play page. COARSE covers five octaves in semitone steps, FINE ±2 semitones. Patch 1 V/octave into J5 and a gate into J3 to play it from a sequencer.

  4. Change what it is. Sweep GEOMETRY slowly: plates, then strings, then bells and inharmonic objects. Lower BRIGHTNESS darkens the high modes, DAMPING shortens the ring, POSITION moves where it is struck.

  5. Hold B3 and bring up BOW or BLOW. Hold B2 for SPACE and MODEL. Let go and the Play page is back, each pot waiting to catch its value before it takes over.

The resonator, in your browser

An illustration computed from Elements' own code

A modal resonator is a bank of filters, one per mode of the object. Elements works out 52 of them from GEOMETRY, BRIGHTNESS and DAMPING, and weights them by POSITION. The plot below does the same arithmetic as Resonator::ComputeFilters, with the same lookup tables, and plays the result.

mode: height = level at the pickup (POSITION) tail = ring time (DAMPING, BRIGHTNESS) ·
At 0 V on J5: note = 24.1 + COARSE + 19, the firmware's formula.
Sound starts on your first press.

What is exact and what is not: mode frequencies, their count (up to 52, stopping below 0.49 of 32 kHz), stiffness from lut_stiffness, the Q from lut_4_decades and its per-mode loss are ported line for line from vendor/eurorack/elements/dsp/resonator.cc. Each mode is then played as a decaying sine (ring time Q ÷ πf, level proportional to the filter's gain) instead of Elements' state-variable filter bank, the pickup weighting uses an exact cosine where Elements uses a fast approximation, and there is no bow, no exciter envelope and no reverb. Strike is an impulse; Blow is white noise through the same response. On the module you hear the real thing.

The voice, control by control

Three pages, and the laws behind them

Play page

PotDoesRange and curve
P1 · COARSEResonator pitch. J5 adds 1 V/octave.0–60 semitones, whole steps with 0.3-semitone hysteresis (upstream's quantized-note law)
P2 · FINEFine tune.±2 semitones, square law: finest at noon
P3 · GEOMETRYThe object's structure: plates and bars, strings, then bells and inharmonic objects. J7 adds CV.0–1
P4 · BRIGHTNESSHow much the high modes are kept. J8 adds CV.0–1
P5 · DAMPINGHow long it rings.0–1
P6 · POSITIONWhere on the object it is excited: the comb-filtering of the modes.0–1

Exciter page · hold B3

PotDoesNotes
P1 · BOWLevel of the bow: a friction model that sustains while the gate is on.First boot 0
P2 · BLOWLevel of the blow exciter: granular noise, or J1's audio when patched and louder than −80 dB.First boot 0 · noise from the card
P3 · STRIKELevel of the strike exciter: mallet, samples, particles, or J2's audio.First boot 80% · samples from the card
P4 · CONTOURThe exciter envelope: gate-length AD at one end, a slow swell at the other, ADSR shapes between.First boot 20%
P5 · FLOWBlow character: a steady breath to granular sputter.First boot 50%
P6 · MALLETStrike character: a mallet, then the recorded samples, then bouncing particles.First boot 30%

Timbre page · hold B2

PotDoesNotes
P1 · BOW timbreColour of the bow.First boot 50%
P2 · BLOW timbreColour of the breath.First boot 50%
P3 · STRIKE timbreBrightness of the strike.First boot 50%
P4 · SPACEMono, then stereo, then reverb. The last eighth of the travel freezes the reverb.0–2 · first boot 0.6
P5 · MODELModal (Elements) · String · Strings (sympathetic ensemble) · Ominous, the two-oscillator FM drone voice Elements shipped as a hidden easter egg.4 zones · first boot Modal
P6 · FMAttenuverter for J6.Quartic: fine near noon, ±12 semitones per volt at the ends

On a first boot the Play page follows the pots, so whatever they point at is what you hear. After that, every page is saved and restored, and each pot must catch its stored value before it moves anything. The pots are shared by every firmware on the card, so after switching they point wherever the last firmware left them.

Jacks and CV

Two audio ins, six CV jacks, two outs
JackRoleHow it is read
J1 · Blow inAudio. Replaces the blow exciter.Elements' noise gate: below −80 dB it fades out, so an unpatched jack's hiss never replaces the internal noise
J2 · Strike inAudio. Replaces the strike exciter.Same gate
J3 · GatePlays the voice, ORed with B1.Raw ADC once per 0.5 ms block: on above 1.5 V, off below 0.5 V. Read one block after the CVs, as upstream, so the pitch is in before the strike
J4 · StrengthHow hard each note is played.0.5 + 0.1 × volts, so ±5 V spans 0–1 and an unpatched jack gives 0.5
J5 · V/OctPitch.Calibrated volts × 12. Jumps over 0.4 semitone land at once, smaller moves glide
J6 · FMFrequency modulation.Through the FM attenuverter (Timbre P6)
J7 · CVGEOMETRY.The SDK's CV matrix; re-routable in Hermetic's web programmer
J8 · CVBRIGHTNESS.Same
J9 · Out mainElements' main output (left).Codec
J10 · Out auxElements' aux output (right).Codec

Elements had CV for damping, position, space and each timbre, with an attenuverter on most. Here only J7 and J8 are free for that, so re-route them in the web programmer if you need a different destination.

Reading the lights

What the buttons and the boot rings say
B1 · Play

The gate and the exciter

White while the gate is on. Otherwise the exciter level in orange over a dim base: dim blue when the samples are loaded, dim amber when /mi/elements.smp is missing or bad.

B2 · Timbre

The resonator

The resonator's level in green over a dim blue, Elements' second meter. Red when the audio callback averages over 80% CPU. Blue while held, as the Timbre page's colour.

B3 · Exciter

Page tint

A dim red tint at rest, the Exciter page's colour while held.

P1 ring · boot

Last session's CPU

For 2.5 s after power-up: the worst audio-block load of the previous session as a fill, green, amber from 75%, red from 90%. One dim blue pip means no data yet, after a fresh flash.

P2 ring · boot

The samples file

For the same 2.5 s: full green, loaded; one red pip, no file; full red, a file was there and was refused.

The samples live on the card

338 KB that do not fit in the firmware

Elements' strike exciter plays recorded samples and its blow exciter reads a noise recording. Together those two tables are 338 KB, and the firmware image has to fit in 480 KB of SRAM beside the SDK. So they ship as a file, and the firmware reads them into SDRAM at boot.

Where

/mi/elements.smp

A folder named mi in the root of the card, not alchemy: the firmware picker lists everything in /alchemy. The build writes the file to build-elements/elements.smp; it is 337,976 bytes.

Checked

Header, counts, CRC-32

A 24-byte header (magic MIES, version 1, the two sample counts, a CRC-32 of the payload), then 128,013 strike samples and 40,963 noise samples. Anything short of an intact file is refused. The bytes are upstream's own arrays, written by a tool that includes the vendored resources.cc.

Without it

Still plays, quieter

The two tables are zeroed: the strike samples and the blow noise go silent. The bow, the mallet synthesis, particles, the external inputs, the resonator and the reverb all still work. B1 rests dim amber and the P2 ring shows red at boot.

The file is read once, at boot, before audio starts. If the card is slow to mount, the samples stay silent until the next power-up. At build 30989c0 its SHA-256 is c1838da0e3ed431f02446bdc349998f1b8089b5139416af14eb39230424e90c5.

Firmware on the card

Carry several firmwares, change between them from the panel

Like the other firmwares for this module, Elements can write any .bin from the card into the module's firmware slot, verify it and reboot into it, from a Settings page.

File on the cardWhat it is
/alchemy/elements_alchemy.binThis firmware (download)
/mi/elements.smpThe exciter samples (download)
/alchemy/*.binAny other Alchemy Lab firmware: Clouds, Marbles, Plaits, Mark, Belt, Smack…

The gesture

Hold B2 + B3 two seconds · tap B1 to the Firmware page · B2 or B3 leaves
PotDoesRing
P1 · FILEPicks a file: one dot per .bin in /alchemy, the chosen one bright. green dots · red: no card · orange: no folder or no files
P2 · FLASHTurn it below 85%, then all the way up. The dip arms it. It compares first: if the file is the firmware already running, nothing is written. teal comparing · solid green: already loaded · orange erasing · blue writing · green verifying · white, then reboot · blinking red: failed, nothing booted
P3 · DFUSame gesture: reboots into the bootloader's update mode and stays there, for a USB flash. violet arming bar

The first Settings page holds the LED brightness (P1, 30% by default; these LEDs get very bright) and the preset gesture: P3 picks a slot, P4 saves or loads it. Elements keeps its working state in its own file on the card, /alchemy/state/elements.st, saved five seconds after the last change once your hands are off the buttons. Up to v0.1.0 it used slot 9; the first boot of v0.2.0 copies that onto the card. The other Lab firmwares keep their own slots, 1–5 and 12–15, so 6–11 are free for presets you save by hand.

Installing

From the card, or through the front USB-C

Download v0.2.0 · built and tested on a computer, not yet run on a module

elements_alchemy.binelements.smpSD card zip · all seven

The zip holds all seven firmwares and the Elements samples, laid out for the card: unzip it onto the card's top level and the .bin files land in /alchemy, elements.smp in /mi. Elements needs both files. Release notes and SHA-256 checksums.

From another firmware

The picker

Copy elements_alchemy.bin into /alchemy and elements.smp into /mi, then pick it from Settings page 2 of any firmware in the family.

First time

Hold B3 at power-on

Hold B3 through the boot window and the module enters update mode. Flash the .bin with Hermetic's web programmer, or pin dfu-util to your module's serial:

make FW=elements program-live DFU_SERIAL=<serial>
Build it

From the repository

make libdaisy
make FW=elements
make -C test test-elements

Never build with a module attached in DFU mode.

Before you flash it

This 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. Mutable Instruments wrote the DSP and has nothing to do with this port either. It has not yet run on a module. Worth reporting if you try it: the CPU readout on P1 after a busy session, whether 0 V with COARSE at noon sounds near note 73, and how the B2 page button gets along with the Settings chord.

How it is built

The layer between Elements and the Alchemy SDK
PieceWhat it is
The DSPelements::Part from pichenettes/eurorack at 08460a6, byte-identical, at 32 kHz with its 16-frame block, so the parameter reads happen at 2 kHz as they did on the original.
The shimWhat cv_scaler.cc, ui.cc and elements.cc did: the pot laws, one-pole smoothing (0.01 for pots, 0.05 where a CV joins), the input noise gates, and the gate read one block late.
Samples out of the imageThe build cuts the two sample arrays out of a copy of resources.cc and checks it found both; the vendored file stays untouched. The engine links to two SDRAM arrays under its own symbol names, filled from the card at boot.
MemoryImage 366 KB, 77% of the 480 KB SRAM region. Part (113 KB) and the reverb buffer (64 KB) in cached D2 SRAM; the samples in SDRAM.
Per-unit characterElements seeded its reverb and resonator modulation from the chip's serial number. This uses the H750's unique ID for the same job, so each module sounds slightly its own.
Pitchnote = 24.1 + 12 × V(J5) + COARSE + 19 + FINE. The 24.1 is upstream's default calibration at 0 V, worked out from its constants: 0 V with COARSE at noon is note 73.1, about 558 Hz. Nobody has checked it by ear yet.
TestsOn a laptop, with address and undefined-behaviour checks: the samples file through the firmware's own reader in five chunk sizes, byte-identical, and six kinds of bad file refused; modal strike, bow and blow, string, strings and Ominous for 2 s each, finite and not silent; the string at note 57 reads 220.17 Hz (+1.4 cents), note 69 441.14 Hz (+4.5 cents).

Left out, compared with a real Elements

Found something? Open an issue. A report from someone playing it is worth more than anything measurable on a laptop.

The rest of them

Four Mutable Instruments ports from one repository, and their siblings

All of Tim's Alchemy Lab instruments, on one page →