draft: false Name: OffAir short-description: AM/Shortwave/Longwave radio simulator with heterodyne whistles, SSB detuning and swelling static summary: >- Tune across a virtual shortwave band the way you tune a real receiver. Two Stations and three interference signals are scattered across the dial and re-randomised on every band change. Approaching a Station you hear a sliding heterodyne whistle, the audio pulls into tune and the static ducks away; off-tune it frequency-shifts on SW and LW or distorts on AM. Knob X sets IF bandwidth and brightness, Knob Y the noise floor. Tap the switch down to cycle AM, SW and LW. Hold the switch up for dead air in baked-in mode, or a Pulse In 1-keyed morse Station 2 in audio-input mode. Pulse In 2 fires curated Insta-ference one-shots. Boot with the switch held down to swap the live inputs for baked recordings and make it self-contained. Language: C++ (Pico SDK + ComputerCard) Creator: Andy Jenkinson (uglifruit) Version: 1.0.1 Status: Released License: MIT date-created: 2026-06-27 date-updated: 2026-08-04 repository: https://github.com/TomWhitwell/Workshop_Computer/tree/main/releases/95_offair2 discussion: https://discord.com/channels/1210238368898879569/1520467972089577623 contact: email: andyuglifruit@hotmail.com social: github: https://github.com/uglifruit tags: - radio - sampler - noise - effect - generative uf2: - path: offair.uf2 name: OffAir v1.0.1 panel: inputs: - id: AudioIn1 name: Station 1 In type: audio description: Station 1 source in audio-input mode; replaced by a baked recording in baked-in audio mode - id: AudioIn2 name: Station 2 In type: audio description: Station 2 source in audio-input mode; becomes a keyed morse tone while the switch is held up - id: CVIn1 name: Tuner type: cv description: Tuning offset added 1:1 to the Main knob, where ±5V covers roughly half the dial each way - id: CVIn2 name: Noise type: cv description: Adds to the Knob Y noise level for voltage-controlled static - id: PulseIn1 name: Shuffle Signals type: pulse description: Rising edge re-randomises the Station and interference layout. In audio-input mode with the switch held up it becomes the morse key instead - id: PulseIn2 name: Insta-ference type: pulse description: Rising edge fires a one-shot from the curated Insta-ference bank, restarting if retriggered outputs: - id: AudioOut1 name: Output type: audio description: Full mix of tuned audio, whistles, static and Insta-ference - id: AudioOut2 name: Just Noise type: audio description: Noise and static only, for processing independently - id: CVOut1 name: Signal Strength type: cv description: Envelope that rises as you tune onto a Station - id: CVOut2 name: Station 1 CV Offset type: cv description: Station 1's offset from the Main knob — patch back into CV In 1, through a slew or direct, to hunt or lock onto Station 1 - id: PulseOut1 name: Station 1 Tuned Gate type: pulse description: Gate high while tuned to Station 1 - id: PulseOut2 name: Station 2 Tuned Gate type: pulse description: Gate high while tuned to Station 2 controls: switch: up: name: Dead Air / Morse description: Held. In baked-in audio mode this mutes both Stations while the interference and their CV and gate outputs continue; in audio-input mode Station 2 becomes a 600Hz morse tone keyed by Pulse In 1 middle: name: Normal description: Standard tuning behaviour down: name: Baked-in Audio Boot description: Held at power-on until all six LEDs flash, this replaces the live inputs with baked recordings for a self-contained radio tap: name: Cycle Band description: A tap cycles AM to SW to LW, re-randomising the dial layout each time knobs: - main: name: Tuning description: Scans across the dial, summed with CV In 1 x: name: Brightness description: IF bandwidth — sets both the Station capture width and the audio brightness, from narrow and muffled counter-clockwise to wide and bright clockwise y: name: Noise Level description: Static floor, silent fully counter-clockwise. Swells and swishes on its own, heaviest on LW, and ducks away when you tune onto a Station leds: - display: list items: - id: led0 name: Station 1 Signal Strength description: Brightness rises as you tune onto Station 1 - id: led1 name: Station 2 Signal Strength description: Brightness rises as you tune onto Station 2 - id: led2 name: SW Band description: Lit on SW. With LED3 both off the band is AM - id: led3 name: LW Band description: Lit on LW. With LED2 both off the band is AM - id: led4 name: Unused description: Not used in this firmware - id: led5 name: Tuning Position description: Indicates the current position across the dial host: notes: | Audio-input mode boots with the switch in any position other than down, or released within the first 200ms, and the two live audio inputs become Station 1 and 2. Baked-in audio mode boots with the switch held down until all six LEDs flash, replacing the live inputs with baked recordings. The baked audio lives in clips.h, generated from your own source files by convert_clips.py — the source audio is not included in this repo. See the README for the conversion workflow and the roughly 2MB flash budget.