A small C99 library for Teenage Engineering PO-32 acoustic data transfers and drum synthesis.
libpo32 reimplements the PO-32 Tonic transfer stack and a compatible drum
voice model. It is not a full PO-32 firmware or UI emulator; it covers the
packet format, acoustic modem, frame decoder, and local drum synthesis needed
to build, send, receive, and preview PO-32 transfers.
| Area | What libpo32 provides |
|---|---|
| Transfer protocol | Build and parse PO-32 patch, pattern, and state packets |
| Acoustic modem | Render transfer frames to DPSK audio for playback into the device |
| Decoder | Recover normalized frames and packets from transfer audio |
| Drum synthesis | Render the PO-32's 21-parameter drum voice locally for preview and testing |
The core is freestanding C99: no libc runtime, no external DSP libraries,
no platform audio APIs, no file I/O. Only the freestanding headers
<stddef.h> and <stdint.h> are used. Suitable for embedded targets and
bare-metal environments.
The PO-32 is not receiving finished drum audio when you transfer a sound or a pattern. It receives structured data:
| Data | Meaning |
|---|---|
| Patch packets | The two patch endpoints per instrument (Left and Right), with the destination instrument slot encoded in the packet |
| Pattern packets | Which instruments trigger on which steps, with the destination pattern slot encoded as pattern_number |
| State packet | Tempo, swing, morph defaults, and the transferred pattern list |
The device then uses its own internal synth engine to turn those parameters into sound.
At a high level, the workflow with real hardware is:
| Step | What you do |
|---|---|
| 1 | Build a transfer in software from patch, pattern, and state data |
| 2 | Render that transfer to a WAV or live audio stream |
| 3 | Put the PO-32 into its normal receive/import flow |
| 4 | Play the rendered transfer audio into the device |
| 5 | The PO-32 decodes the packets and writes them to the sound or pattern slots named inside those packets |
From the repository root, configure, build, run tests, then the demo:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
ctest --test-dir build --output-on-failure
./build/po32_demoOptional, but recommended for local development:
./scripts/install-git-hooks.shThat enables the repo-managed pre-commit hook, which runs clang-format on
staged .c and .h files before each commit and validates commit subjects
against Conventional Commits. The repo-managed pre-push hook runs the static
analysis script before push.
The demo builds a transfer frame, renders it to audio, decodes it back
(verifying a lossless roundtrip), synthesizes a drum hit, and writes two
WAV files: demo_modem.wav and demo_kick.wav.
| Command | Purpose |
|---|---|
./build/po32_example |
Minimal roundtrip: encode, render, decode, and verify |
./build/po32_demo |
End-to-end demo: transfer frame build/render/decode plus local drum synthesis |
./build/po32_pattern_editor |
Interactive PO-32 pattern editing and WAV export |
./build/po32_decode_capture <input.wav> <out-dir> |
Packet and pattern dumps from a transfer WAV |
See CONTRIBUTING.md for local setup, verification commands, and the Conventional Commits policy used for SemVer-friendly history.
Copyright (c) 2026 Eric Lewis. Licensed under the MIT License. See LICENSE.