Teenage Engineering's PO-32 acoustic modem and synth implementation

libpo32 is a lightweight C99 library that reimplements the PO-32 Tonic's acoustic transfer protocol and drum synthesis engine, designed for embedded systems and bare-metal environments.
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.
- Overview
- Using It With a PO-32
- Getting Started
- Examples
- Public API
- Documentation
- Project Layout
- Contributing
- License
| 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_demo
Optional, but recommended for local development:
./scripts/install-git-hooks.sh
That 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 |
| Header | Responsibility |
|---|---|
core/include/po32.h |
Transfer builder, packet helpers, renderer, and decoder |
core/include/po32_synth.h |
Drum synthesizer |
| Document | Purpose | |---|---| | Architecture | How the codec works | | Protocol | Wire format details | | C API | C function reference | | Synth | Synthesizer signal path | | Patch Parameters | The 21 parameters | | Examples | Supported example programs | | Contributing | Local setup, checks, and commit conventions |
| Path | Purpose |
|---|---|
core/src |
Core C implementation |
core/include |
Public C headers |
core/examples |
Supported C examples |
core/tests |
Core test coverage |
core/docs |
Architecture, protocol, and API notes |
bindings |
Language bindings |
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.
Source: Hacker News










