draft: false
Name: Bootleg Radio
short-description: "A lo-fi bootleg tribute to Music Thing's Radio Music: tune through WAV files on a USB stick, like a pirate station"
Language: C++ (Pico SDK + ComputerCard)
Creator: Joep Vermaat
Version: "1.0.0"
Status: Released
License: MIT
Editor: none
date-created: 2026-10-03
date-updated: 2026-10-04
contact:
email: joep@joep-i.nl
# Vendored, unmodified and under their own terms:
# ComputerCard.h
# (c) Chris Johnson, MIT
# fatfs/ (FatFs, R0.16)
# (c) ChaN, FatFs license (see fatfs/LICENSE.txt)
# The usb_msc_host example this card is adapted from was contributed by
# Chris Johnson to the Workshop_Computer repository (PR #437).
uf2:
- path: UF2/bootleg_radio.uf2
name: Bootleg Radio 1.0.0
tags:
- sampler
- playback
- wav
- usb-host
- radio
- utility
summary: |
A lo-fi bootleg tribute to Music Thing Modular's Radio Music - not a
replacement, but a cheaper, grubbier cousin. Named for the 538 AM pirate
broadcasters off the Dutch coast (and the Botlek, the grimy Rotterdam
docklands where sub- and pirate culture ran thick), it deliberately keeps the
hiss and the seams. Load a USB stick with WAV files, plug it into the
Computer's front USB-C jack, and tune through them like radio stations. For a
ready-made start, the
[Radio Music Suggested Audio](https://www.musicthing.co.uk/Radio_Music_Suggested_Audio/)
page is a great set of loops and samples to load onto the stick and try the
card. The Main knob and CV in 1 pick the station, the X knob and CV in 2 set the
tape speed, the Y knob and Audio in 1 set the loop start, and Audio in 2 sets
the loop length. Each station loops over its window; the switch retriggers,
selects banks, or (held) changes the tune mode.
Files are grouped into banks: the root directory is bank 0, and each
subdirectory that holds WAV files is another bank (up to 32). Hold the switch
up and turn Main to change bank; a new bank starts at its first station. The
root is always bank 0 even if it holds no WAVs, in which case the card starts
silent until you pick a folder. Banks and the stations within them are
natural-sorted (case-insensitive, digits compared as numbers), so the order
matches Finder; a bank holds up to 64 stations.
Files must be uncompressed 16-bit PCM, mono or stereo, at any sample rate up
to 192kHz; they are resampled to 48kHz on the fly. This is a hacker's sampler
rather than a pristine one: the DAC is 12-bit and the resampling is simple
linear interpolation, which is part of the character.
Tuning can be a "synchronised jump" - the new file picks up at the same
proportional position where the old one stopped - so a slow sweep through the
stick keeps its place instead of restarting everything at the beginning. This
is the default "Sync" mode; holding switch-down toggles to "Loop" mode, where a
new station starts at its loop start point. A deliberate retrigger, or reaching
the loop end, restarts from the live loop start point.
Needs a Rev 1.1 or later Computer (the revision with USB host support), and
nothing else may be in the front USB socket, because the Computer has to act
as a USB host.
panel:
inputs:
- id: CVIn1
name: Station CV
type: cv
description: >
Selects the station, added to the Main knob. The whole CV range sweeps
evenly across every station in the current bank; while the switch is held
up it selects the bank instead. When the jack is unpatched the knob works
alone.
- id: CVIn2
name: Speed CV
type: cv
description: >
Tape speed, added to the X knob: about -6V is the slowest (-2 octaves),
0V is normal speed, +6V the fastest (+2 octaves). The CV inputs are
bipolar, so a unipolar source sweeps only half the range.
- id: AudioIn1
name: Loop Start CV
type: cv
description: >
Loop start point, added to the Y knob: about -6V is the start of the
file, +6V the end. The audio inputs are DC-coupled, so they read a
steady voltage just like a CV input.
- id: AudioIn2
name: Loop Length CV
type: cv
description: >
Loop length, as a fraction of the file: about -6V is a very short loop,
0V is half the file, +6V the whole file. Unpatched, the loop runs to the
end of the file.
- id: PulseIn1
name: Clock
type: pulse
description: >
External clock for the two CV outputs (the triangle LFO and the random
CV). Unpatched, they run from an internal 120 BPM clock; patch a clock
here to drive them from it. The tempo glides to the new rate and falls
back to 120 BPM if the clock stops.
- id: PulseIn2
name: Retrigger
type: pulse
description: >
A rising edge retriggers the current station from the loop start, just
like a short switch-down tap.
outputs:
- id: AudioOut1
name: Audio Out 1
type: audio
description: Left channel (mono files appear on both outputs).
- id: AudioOut2
name: Audio Out 2
type: audio
description: Right channel (mono files appear on both outputs).
- id: PulseOut1
name: Loop Gate
type: pulse
description: >
By default, high while the loop is playing and low during the wrap/seek
gap, so other modules can follow the loop window. settings.txt can set it
to a loop-wrap tick, the active clock pulse, or off.
- id: PulseOut2
name: Wrap Tick
type: pulse
description: >
By default, a short pulse each time the loop wraps around to the start.
settings.txt can set it to the loop gate, the active clock pulse, or off.
- id: CVOut1
name: Random CV
type: cv
description: >
A random stepped voltage (bipolar), with a new value on every clock pulse
(2Hz at the internal 120 BPM). Patch it into any input to step a
parameter - for example CV in 2 to step the tape speed, or Audio in 1 to
jump the loop start.
- id: CVOut2
name: Triangle LFO
type: cv
description: >
A bipolar triangle, one cycle per 40 clock pulses (20 seconds at 120 BPM,
stretching or shrinking with an external clock), so the card doubles as a
slow LFO for the rest of the rack. Patch it into CV in 1 to sweep through
the stations, or CV in 2 to sweep the tape speed.
controls:
switch:
down:
name: Retrigger / Mode
description: >
Momentary. A short tap restarts the current station from the loop start,
so the switch acts as a trigger input for the loop. Holding it for about
a second toggles the tune mode between Loop and Sync; the whole panel
blinks 2 times for Loop and 3 times for Sync.
up:
name: Select Bank
description: >
While held, the Main knob and CV in 1 select the bank (root = bank 0,
then each subfolder with WAV files). A new bank starts at its first
station; releasing the switch returns Main to selecting stations.
middle:
name: Play
description: >
Playback runs normally. A station loops over its window forever; the
card never advances on its own.
knobs:
- main:
name: Station / Bank
description: >
Chooses the station within the current bank; CV in 1 adds to it, so
patching a CV lets you tune by voltage as well as by hand. While the
switch is held up, the same knob selects the bank instead.
x:
name: Tape Speed
description: >
Playback rate from -2 to +2 octaves, exponential around a centre of
normal speed. Slower also plays lower, like slowing a tape. CV in 2
adds to it.
y:
name: Loop Start
description: >
Where the loop begins, as a fraction of the file. The loop plays from
here for the loop length, then wraps back. Audio in 1 adds to it.
leds:
- display: list
items:
- id: LED0
name: Left Level
description: Brightness follows the left output level.
- id: LED1
name: Right Level
description: Brightness follows the right output level.
- id: LED2
name: Playing / Mode
description: >
Off when idle. Steady while a station is playing in Sync mode, and
slowly blinking while playing in Loop mode, so it shows both the
play state and the current tune mode.
- id: LED3
name: Station Change / No Files
description: >
Blinks for about half a second when the station changes. Lights
steadily (with LED 4) if a mounted stick has no WAV files in the
selected bank, or if none of the files found could be played. Dark in
the "quiet" LED mode (settings.txt).
- id: LED4
name: USB Mounted
description: Lit while a USB stick is detected.
- id: LED5
name: Underrun / Mount Fault
description: >
Flashes if the stick cannot feed the buffer fast enough. Lights
steadily (with LED 4) if the filesystem on a detected stick could
not be mounted. Dark in the "quiet" LED mode (settings.txt).
host:
usb:
- name: USB flash drive
role: storage
description: >
A FAT32 or exFAT USB stick holding 16-bit PCM WAV files in its root
directory and/or subfolders (each subfolder with WAVs becomes a bank),
plugged into the Computer's front USB-C jack. Needs a Rev 1.1
or later board, because the Computer acts as USB host. Use a data cable
or adaptor, and keep the stick the only thing in that socket. The card
mounts a wide range of sticks: Master Boot Record, GUID Partition Map
and whole-disk (superfloppy) layouts are all supported, as are sector
sizes from 512 to 4096 bytes. A GPT data volume must be the Microsoft
Basic Data type, which is the default for FAT/exFAT.
notes: |
The card never writes to the stick, so nothing on it can be changed by
accident. WAV files are natural-sorted (case-insensitive, digits compared as
numbers), so the station and bank order matches Finder. Files are read from
the root directory and from each subfolder that holds WAV files. An optional
settings.txt in the root sets the power-on mode, start bank, internal clock
tempo, triangle rate, the two pulse-output modes and the LED mode; it is read
once per mount, and a missing or malformed value falls back to the default.