FOX RUN LABS
← Selected work

02 / SWIFT · macOS · PARSING & AUDIO

QBPlay

Text becomes sound. A retro idea with a native audio pipeline.

SwiftUIMML interpreterAVAudioEngineAccelerate
Explore the repository
QBPlay macOS window with a QBasic-inspired music editor and Play and Export buttons
A QBasic-inspired interface, running as a native macOS application.

THE PROBLEM

Bring a small music language to life.

QBasic’s PLAY command describes music using compact text commands. QBPlay interprets a useful subset of that language in a native macOS application: enter a tune, hear it, and export the rendered audio as a WAV file.

From characters to samples

The project separates lexical analysis, interpretation, musical events, synthesis, and playback. The lexer identifies commands; the interpreter applies tempo, octave, duration, and articulation state. Musical events carry timing and pitch into a renderer that generates the sample data.

MML input
Commands
Interpreter
Music events
Synthesizer
Audio samples

AVAudioEngine handles playback, while Apple Accelerate supports waveform generation. The same rendered result can be used for listening and export, keeping those paths connected to one synthesis implementation.

Designing how a note sounds

The renderer starts from a sine wave and shapes it toward a square-like waveform. Short attack and release envelopes reduce clicks at note boundaries. Legato notes preserve oscillator phase across connected notes; normal and staccato articulation leave different amounts of silence within a note’s duration.

This makes the project more than a text parser: musical timing must become a precise number of samples, and transitions between events affect the result that a listener hears.

Compatibility with a deliberate boundary

The supported syntax includes named and numbered notes, accidentals, rests, dotted durations, tempo, octave shifts, and articulation. QBasic’s MB and MF commands are accepted for compatibility but do not change playback. The app produces a single monophonic stream; it does not emulate QBasic or support every historical PLAY feature.

Evidence and next steps

The repository provides a screenshot, sample audio, source code, and build instructions. Its source separates parsing from rendering, and the synthesis implementation explicitly handles envelopes and phase continuity.

Automated parser and renderer tests would strengthen the next iteration: malformed commands, error positions, note durations, rest silence, sample counts, and finite output values. A further practical question is how to bound memory use for long input, because the renderer assembles the complete output in memory.

Listen to the repository’s audio example ↗
This case study describes the checked-in implementation. It does not claim a current passing automated test suite. Build requirements, syntax details, and credits are documented in the repository.

KEEP EXPLORING

CHIP-8 — beyond the screen