draft: false Name: SPECTRAL short-description: A spectral filter bank with randomly modulated logarithmic bands — the Spectral Clouds mode from Kammerl's Clouds fork, ported to the Workshop Computer Language: C++ (Pico SDK + ComputerCard) Creator: Andy Jenkinson (uglifruit) Version: "1.0.0" Status: Released License: MIT repository: https://github.com/uglifruit/WorkshopSpectral Editor: none date-created: 2026-08-23 date-updated: 2026-08-27 # This card is a port of the "Spectral Clouds" playback mode from Julius # Kammerl's fork of Mutable Instruments Clouds (https://www.kammerl.de/audio/ # clouds/, https://github.com/jkammerl/eurorack), itself derived from Clouds # by Emilie Gillet. Both are MIT; this card keeps the same licence. See # README.md's Credits section. contact: social: github: https://github.com/uglifruit uf2: - path: UF2/spectral.uf2 name: SPECTRAL 1.0.0 tags: - effect - spectral - fft - filter - texture - freeze - tape-delay summary: | SPECTRAL runs a live FFT over Audio In 1 and divides the spectrum into 4 to 128 LOGARITHMICALLY spaced bands. Every band gets a random gain, re-rolled on a trigger and smoothed over time; bands below a threshold shut entirely. Bands opening and closing is the sound — a high-resolution filter bank that keeps morphing but stays musical, because the divisions are logarithmic rather than linear.

It is a spectral filter, not a granular processor and not a reverb. Feed it anything sustained — pads, drones, noise, feedback, a whole mix — and it carves moving holes in the spectrum. Low band counts (4–8) give broad obvious sweeps, close to a random multi-band gate. High counts (64–128) give fine shimmering comb-like textures. Slow smoothing lets bands drift open and shut like weather; fast smoothing makes them snap, which with a fast re-roll rate becomes a stuttering spectral gate.

TEXTURE randomises the phase of every bin, smearing transients into a diffuse wash — the part that earns the "clouds" name. FREEZE holds the current magnitude spectrum while still tracking incoming phase, so a held sound stays alive instead of becoming a static drone. That makes it an effect ON a signal rather than a sampler: the input keeps supplying phase while frozen, so pulling the patch cable thins the sound out rather than sustaining it, and freezing during a gap holds a correspondingly quiet spectrum. A short press on the momentary Down position toggles that freeze; HOLDING Down for two seconds instead selects SEALED freeze, which holds each bin's phase advance as well as its magnitude — nothing of the live input reaches the output (leak −69dB rather than −30dB) and the sound sustains at full level with the input unplugged, as a held chord rather than a static buzz. Any short press returns to live.

Both outputs carry the same wet signal. Mix the dry signal back externally, and patch through a stereo effect downstream if width is wanted.

The switch's two stable positions select knob pages. Middle is page one: Main sets PROBABILITY (how many bands are open), X sets BANDS (4–128), Y sets SMOOTHING. Up is page two: Main sets TEXTURE, X sets RE-ROLL RATE, Y sets OUTPUT LEVEL. Down is the spring-loaded momentary position and toggles FREEZE on each press. Knobs are always live on the page you are looking at. CV In 1 and 2 offset PROBABILITY and BANDS; Pulse In 1 re-rolls the bands, Pulse In 2 freezes while held. CV Out 1 follows spectral density, and CV Out 2 reports the measured DSP load so the headroom can be checked on a voltmeter.

ALT-BOOT: holding the switch DOWN at power-on starts TAPE mode, adding a tape-style delay after the spectral engine — wow and flutter from two detuned LFOs moving the read head up to 4ms, damping so repeats darken, and a saturating feedback path. Page 2 becomes TIME, FEEDBACK and WOW; page 1 is unchanged. Even LEDs show a normal boot, odd LEDs the alt-boot.

N=1024, hop 256 (75% overlap), sine window, running at 192MHz with all FFT work on core 1 — the audio ISR only fills a ring. The band ratio the original stores in a 127-entry table turned out to be exactly size^(1/(k+1)), verified to 2e-10 against every entry, so it is computed directly rather than shipped; that also makes it correct at this card's FFT size rather than Clouds' larger one.

The fixed-point DSP is verified on the host as well as on hardware — FFT accuracy, rect/polar conversion, overlap-add gain, ring timing, band layout and the tape delay each have a test in tools/ (see docs/FFT_VALIDATION.md, which documents the real bugs those tests caught). Flash 1.5%, RAM 70%, and the DSP runs at about 68% of its per-frame budget at 192MHz — measured on hardware and reported live on CV Out 2. panel: inputs: - id: AudioIn1 name: In type: audio description: > The signal to process. Wants something sustained and harmonically rich - pads, drones, noise, cymbals, a whole mix. Percussion smears, since the analysis window is 1024 samples. - id: CVIn1 name: Prob type: cv description: Summed with the Main knob on page one. - id: CVIn2 name: Bands type: cv description: Summed with the X knob on page one. - id: PulseIn1 name: Re-roll type: pulse description: > Rising edge assigns every band a fresh random gain. With RE-ROLL RATE fully anticlockwise this is the only thing that changes them. - id: PulseIn2 name: Freeze type: pulse description: > Holds the magnitude spectrum while high, independently of the switch latch. Always the normal (leaky) freeze, never SEALED. outputs: - id: AudioOut1 name: Out type: audio description: The filtered signal. Mono - both outputs carry the same thing. - id: AudioOut2 name: Out type: audio description: Duplicate of Audio Out 1. - id: CVOut1 name: Density type: cv description: Follows how much of the spectrum is currently open. - id: CVOut2 name: DSP Load type: cv description: > Diagnostic. Measured core-1 load as a fraction of the per-frame budget; full scale means core 1 is exactly keeping up. Sits around 4V (about 68%) in normal use. - id: PulseOut1 name: Re-roll type: pulse description: Fires on every re-roll, triggered or spontaneous. - id: PulseOut2 name: Open Gate type: pulse description: High while more than half the spectrum is open. controls: switch: middle: name: Page 1 description: > Main, X and Y control PROBABILITY, BANDS and SMOOTHING - the performance controls. up: name: Page 2 description: > Main, X and Y control TEXTURE, RE-ROLL RATE and OUTPUT LEVEL. In the TAPE alt-boot this page becomes TIME, FEEDBACK and WOW instead. tap: name: Freeze description: > Briefly press Down to toggle freeze, which holds the magnitude spectrum while still tracking incoming phase. HOLDING Down for two seconds instead selects SEALED freeze, which holds each bin's phase advance as well, so nothing of the live input reaches the output. Any short press returns to live. knobs: - when: { z: middle } main: name: PROBABILITY description: > How many bands are open. A density control rather than a volume one: most of the level arrives by about halfway, and the top half reads as increasing density and smoothness. x: name: BANDS description: > 4 to 128 logarithmically spaced bands. Low counts give broad obvious sweeps; high counts give fine comb-like textures. y: name: SMOOTHING description: > How fast band gains morph. Snaps at the bottom of the range, then sweeps from about 50 ms to 2.6 s. - when: { z: up } main: name: TEXTURE description: > Phase randomisation depth. Smears transients into a diffuse wash, and suppresses the input leak heard during freeze. In TAPE mode this knob is TIME - delay length, 25 ms to 1.35 s, slewed so that moving it bends the pitch of sounding repeats. x: name: RE-ROLL RATE description: > Fully anticlockwise means never re-roll on its own - bands change only on Pulse In 1. Above that, roughly 3 s down to continuous. In TAPE mode this knob is FEEDBACK, roughly 3 to 40 repeats. y: name: OUTPUT LEVEL description: > Holds its current value until the knob is actually moved, so changing page never drops the volume. In TAPE mode this knob is WOW - the depth of the pitch wobble, up to about 4 ms of read-head movement. leds: - display: list items: - id: "0" name: Density (low) - id: "1" name: Density (mid) - id: "2" name: Density (high) - id: "3" name: Freeze description: Steady for normal freeze, slow pulse for SEALED freeze. - id: "4" name: Page 1 description: > Lit on page one. At boot, LEDs 0, 2 and 4 light together for about three quarters of a second to show a normal boot. - id: "5" name: Page 2 description: > Lit on page two. At boot, LEDs 1, 3 and 5 light together to show the TAPE alt-boot.