Firmware for the Hermetic Modular Alchemy Lab V2 · mi-alchemy v0.2.0 · the Parasites build

WARPS

Two signals in, one out. A carrier on J1 and a modulator on J2 are crossfaded, folded, ring-modulated, XORed, compared or vocoded into something neither of them was.

Built and native-tested · not yet flashed or heard

The collider

This is Warps' META mode in the browser, using the firmware's own code. ALGORITHM goes through the same pot curve. The six cross-modulation algorithms, how neighbouring algorithms blend, the skewed TIMBRE and the handover to the vocoder are ported line for line from modulator.cc. So are its lookup tables: the crossfade, the bipolar fold and the pot curve are embedded here. Move ALGORITHM and watch the sidebands appear.

CARRIER (B1 on the panel)
loops two seconds of the output

What is simplified. Warps oversamples ×6 around the cross-modulation and runs each input through a soft-saturating VCA. This runs at 96 kHz without oversampling, and each input is just scaled by level², the drive Warps uses. Its internal oscillators are band-limited, and these are not. The vocoder is not simulated: past about 0.68 on the algorithm scale the output fades to the modulator, as on the module, and above 0.73 this page stops.

What it does

This is Warps, Emilie Gillet's meta-modulator for Mutable Instruments, in Matthias Puech's Parasites build, compiled for the Alchemy Lab. The engine is warps::Modulator from mqtthiqs/parasites at 32fa66f, unmodified apart from one marked fix. It runs at Warps' own 96 kHz, in 60-frame blocks.

META mode is stock Warps. ALGORITHM sweeps crossfade, fold, analog ring modulation, digital ring modulation, XOR, comparator and vocoder, and TIMBRE is the parameter of whichever algorithm you're on. Parasites adds eight more modes: Doppler, Fold, Chebyshev, Frequency shifter, Bitcrusher, Comparator, Vocoder and Delay.

Nothing on J1? Pick an internal carrier with CARRIER (sine, triangle or saw), as with Warps' button. LEVEL 1 then sets its pitch, J5 adds 1 V per octave, and TUNE on the Setup page transposes it. Whatever is on J1 becomes through-zero FM into that oscillator.

Carrier in on J1, modulator in on J2, out on J9, and aux on J10. With the internal carrier on, the aux output is that oscillator.

The panel

Pick a page, then hover or tap any pot, button or jack. The rings are drawn the way the firmware draws them.

Select a control

The panel

6 pots × 2 pages · 3 buttons · 10 jacks
Front view, left to right and top to bottom: P1, B1, P2; P3, B2, P4; P5, B3, P6. Below them the USB-C port and the ten jacks: inputs on the left, outputs on the right.

Buttons

B1 · CARRIER. A tap steps CARRIER, which is Warps' button: external, sine, triangle, saw. In Doppler it sets the room size, and in Delay the loop type. The stored value moves, so the ring follows and the change is saved, and the CARRIER pot has to catch its new value before it takes over again.

B2 · MODE. A tap steps MODE through META and Parasites' eight. It stands down while B3 is held, so the B2 + B3 Settings chord never steps the mode on the way in.

B3 · SETUP. Hold it to show the Setup page: IN GAIN and TUNE. The other four Setup pots do nothing. Hold B2 + B3 for two seconds to open Settings.

The nine modes

MODE lists META first, because that's stock Warps, then Parasites' modes in their own order. The knobs change meaning with the mode. This table follows the firmware's design notes, which come from the Parasites documentation.

ModeLEVEL 1LEVEL 2ALGORITHMTIMBRECARRIER

META: where each algorithm sits on ALGORITHM

The pot goes through Warps' lut_pot_curve, which gives each algorithm a flat spot. Between flats, neighbouring algorithms crossfade. Internally the value is multiplied by 8: 0 is crossfade, 1 fold, 2 analog ring mod, 3 digital ring mod, 4 XOR, 5 comparator. From about 0.68 the output fades toward the vocoder, which takes over completely above 0.73.

AlgorithmWhat TIMBRE doesThe code
CrossfadeBalance from modulator to carrier, on an equal-power curvex₁·fade_in(p) + x₂·fade_out(p)
FoldFold depth: sum and product of the two, through a bipolar wavefolderfold((x₁+x₂+x₁x₂/4)(0.02+p))
Analog ring modDrive into a diode ring model (Parker, DAFx-11), then a soft limitD(m+2c)+D(m−2c), ×(4+24p)
Digital ring modDrive into a clean multiply, softly limited4x₁x₂(1+8p), then r/(1+|r|)
XORBlend from the sum to the bitwise XOR of the two as 16-bit words(x₁ ⊕ x₂) vs 0.7(x₁+x₂)
ComparatorMorphs through four comparisons: min, threshold, window, window 24-step sequence
VocoderFormant shift; ALGORITHM past 0.75 sets the release time20-band filter bank

Jacks and CV

JackDoesHow it is read
J1Carrier inCodec left. With an internal carrier on, it is through-zero FM into that oscillator.
J2Modulator inCodec right.
J3CV → ALGORITHMThe SDK's CV matrix, summed into the knob.
J4CV → TIMBRECV matrix.
J5V/Oct → internal carrierThe calibrated jack, 12 semitones per volt, read every block. Jumps over 0.4 semitones land at once and smaller changes glide, as upstream.
J6 / J7CV → LEVEL 1 / LEVEL 2CV matrix, summed. See the note below.
J8UnassignedRoute it to any knob in the web programmer.
J9 / J10Out / auxThe Modulator's main and aux outputs.

Level CV adds to the knob here; it isn't a VCA. On a real Warps, a cable in a LEVEL jack turns it into a VCA (drive = pot² × CV × 1.6). The module finds out with a probe signal on the jack's normalling. The Lab can't sense a cable, so this firmware always behaves as if nothing is patched (drive = level²), and CV adds to the knob. On a real Warps the LEVEL 1 CV jack is also the V/Oct input. Here V/Oct has its own jack, J5.

Reading the lights

B1 shows CARRIER in Warps' button colours: dim for external (or tiny, or open), then green, yellow and red.

B2 is the mode's colour (see the table above). It turns red when the audio callback averages over 80 % CPU.

B3 has a dim Setup tint.

P1 at boot. For 2.5 s after power-up, the P1 ring shows the previous session's worst audio-block load. Green is under 75 %, amber under 90 %, and red is 90 % or more. A single dim blue dot means there's no data yet. At 96 kHz this is the number to watch, most of all in Vocoder mode.

Firmware on the card

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

warps_alchemy.binSD 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. Release notes and SHA-256 checksums.

Put warps_alchemy.bin in the /alchemy folder on the SD card, beside the other Alchemy firmwares, and pick it on Settings page 2:

  • P1 FILE picks the file.
  • P2 FLASH writes it: turn below 85 %, then past 95 %.
  • P3 DFU does the same gesture, and reboots into the bootloader.

The firmware picker is the same in every mi-alchemy firmware and in Mark, Belt and Smack.

Where it saves. Warps keeps its working state in its own file on the card, /alchemy/state/warps.st, and saves it about five seconds after the last change, once no button is held. Up to v0.1.0 it used preset slot 7; 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.

First boot after a flash: MODE is META and CARRIER is external, so a fresh module is stock Warps on its jacks. IN GAIN is at 0 dB and TUNE at 0. The other PLAY pots take whatever position they're in.

Status

Proven on a computer

  • Builds to a 393 KB image, 80 % of the SRAM region. The Modulator (123 KB) sits in the Lab's D2 RAM.
  • Digital ring mod of 1000 Hz × 200 Hz gives the 800 Hz and 1200 Hz sidebands, with the inputs suppressed by more than 20 orders of magnitude.
  • Every mode with all four CARRIER states runs for a second at 96 kHz. The output stays finite and never sticks at full scale. Delay runs in all four loop types, which exercises the fix below.
  • The internal sine measures 370.0 Hz at LEVEL 1 noon and 740.0 Hz with +1 V on J5.

Not yet tested on the module

  • Nothing has been flashed or heard.
  • CPU at 96 kHz on the Cortex-M7. It should fit, since Warps ran this at 96 kHz on a 168 MHz STM32F405, but it's unmeasured. Watch the Vocoder.
  • Input level. IN GAIN starts at 0 dB, and the Lab's codec scaling against Warps' input range is unknown. Fold, drive and the comparator all respond to level.

Left out

  • The patched-cable probe (see Jacks), stock Warps' hidden frequency shifter (Parasites has its own), and Warps' own calibration. The Lab's factory CV calibration is used instead.
  • Stock Warps as a separate tenth mode. META is already stock Warps' algorithms.
  • Launchpad and USB audio. This v0.1 is HostLink only, and it never changes the card's USB setting, so the other firmwares keep theirs.

One fix to the vendored code. Parasites' delay never wrapped its read index above the buffer size. ASan found it while Warps was being ported to the Daisy Patch (Meld), and it's marked in the source and listed in vendor/VENDOR.md.