Barber's Pole
Firmware for Workshop System Computer (Music Thing Modular)
An infinite glissando — Shepard-Risset tones that rise or fall forever, as sine tones or by octave-stacking live audio.
- Distribution
- Prebuilt image you flash yourself
- Source
- github.com https://github.com/TomWhitwell/Workshop_Computer/tree/main/releases/104_barbers_pole
- Homepage
- computer.musicthing.co.uk https://computer.musicthing.co.uk/programs/104-barbers-pole/
- Synced from
- upstream metadata, raw.githubusercontent.com https://raw.githubusercontent.com/TomWhitwell/Workshop_Computer/main/releases/104_barbers_pole/info.yaml. Corrections belong upstream.
- effect
- synth
- pitch-shifter
- shepard
- barbers-pole
- glissando
- scale
- octave-stack
- percussion
- cards
Description
BARBER'S POLE generates Shepard-Risset tones: the auditory illusion of a pitch that glides forever upward or downward without ever leaving its range. Octave-spaced components slide together through a fixed spectral envelope, each fading in at the bottom and out at the top; because the stack is octave-spaced, sliding it by one whole octave returns it exactly to where it started, so the glide loops seamlessly.<br><br>
Main sets speed and direction, with a deadzone at noon so the stationary position can be found by feel — anticlockwise descends, clockwise ascends, and CV In 1 is summed in. X sets density, 3 to 11 octave layers, stepped discretely with hysteresis so knob jitter cannot retrigger a change. Y crossfades between two sources: the internal sine bank, and your own signal OCTAVE-STACKED.<br><br>
The live path transposes whatever is patched into Audio In 1 into N octave-spaced copies, weighted by the same window as the oscillators - so a 220 Hz partial appears at 55, 110, 220 and 440 Hz and each copy rises and fades exactly as an oscillator layer does. The internal voice is octave-stacked sines; this is octave-stacked you. Feed it anything with clear pitch content.<br><br>
Switch Up is page two: Main quantises the glide to smooth glissando, 12-ET chromatic, major, minor or pentatonic; X sets stereo width; Y sets output level. Snapping is slewed over about 1.4 ms rather than jumped, because twelve oscillators stepping together is audible as a thump.<br><br>
Switch Down is spring-loaded and toggles FREEZE on each press. Audio In 2 is a HOLD gate doing the same thing - it stops the glide while high and resumes from exactly where it paused, so the glide does not run on underneath. Pulse In 1 is an EVENT rather than a gate: its rising edge advances a scale step in the stepped modes, and because it never holds the glide, stepping and gliding work together - park Main at centre for pure manual stepping, or leave it off-centre and the pulses nudge an already-moving pole. Pulse In 2 reverses the glide while held. CV In 1 and 2 offset speed and density. CV Out 1 is the master phase as a 0-1V ramp - one octave per cycle, so an oscillator tracks the pole in tune - and CV Out 2 is the window level at that phase, so the two together drive a VCA and oscillator as one Shepard layer made external.<br><br>
ALT-BOOT - HIDDEN BARBER: holding the switch DOWN at power-on makes the pole climb SILENTLY. A trigger on Pulse In 1 voices a ping at whatever pitches the pole has reached, and that ping decays WITHOUT climbing - it is a snapshot, not a window onto the moving stack. Trigger repeatedly and each ping comes from a different point on the pole, building a chord out of one rising structure, so the barber's pole becomes something you play rather than something you listen to. Four voices, oldest stolen. Page-two X sets the decay, 17ms to 1.7s; Main still quantises. Patch Pulse Out 1 back to Pulse In 1 and it strikes itself once per octave. Note that four voices of twelve layers each, with the live input octave-stacked through all of them, is close to what an RP2040 can do at 48kHz - trigger fast enough that all four ring at once, with a long decay and the input mixed in, and the card WILL distort. That is the processor running out of time rather than a fault, and no setting removes it; shorten the decay, use fewer layers, or play a little more sparsely. With Y clockwise the live input is gated by the ping envelope AND transposed to the struck pitches, so your own signal is what rings.<br><br>
All fixed point: the RP2040 has no FPU, so a float multiply costs ~360ns against a 20.8us per-sample budget. Two economies make a eleven-layer stereo bank affordable — because the layers are exactly an octave apart every layer's increment is layer 0's shifted left by i, so ONE exponential lookup serves all eleven at 1.5kHz rather than 48kHz; and the octave stack's read heads all share one delay buffer, which is the card's single large allocation. The envelope reuses the first half of the sine table rather than needing one of its own, and sums to exactly N/2 at every layer count and phase.<br><br>
The fixed-point DSP is verified on the host before flashing — window constant-sum, exponential accuracy, quadrature and sideband rejection, scale quantisation across the octave wrap, delay loop stability run at DC, and end-to-end gain. Two of those tests caught real bugs during development: a truncated window lookup that rippled at odd layer counts only, and an output stage running 4dB too hot. A renderer (tools/shepsim.py) runs the same integer engine to WAV so the card can be heard before flashing, and checks the octave wrap for a discontinuity — calibrating itself against a deliberately broken build on each run, so a detector that cannot fire is never mistaken for a pass.<br><br>
Flash 1.4%, RAM 57%, both from the linker. Measured on hardware, the normal engine has comfortable margin; HIDDEN BARBER at four simultaneous voices with the live input mixed in sits close to the ceiling - see the note above.
Install notes
Copy the UF2 onto the Computer's program card (RP2040 bootloader drive).
Version history
| Version | Date | Notes |
|---|---|---|
| 1.0.0 | 2026-08-30 | Version and date from the card's info.yaml. |