C++ firmware library for embedded audio on ARM Cortex-M
What is Sound Byte Libs?
Sound Byte Libs is a library for building musical instruments and audio applications on 32-bit ARM microcontrollers.
Write once, run on multiple targets. SBL provides useful building blocks without imposing structure on your application. Through compile-time template polymorphism, you get hardware portability with zero-overhead abstractions.
Key features:
- Cross-platform: Same code compiles for RP2040, RP2350, STM32H7
- Bare-metal: No vendor HALs - SVD-generated register definitions
- Tiny binaries: 1KB blinker, 13KB synth voice, 24KB polyphonic instrument
- Complete DSP toolkit: Oscillators, filters, envelopes, delay lines, lookup tables
- MIDI support: Stream parser with running status, channel filtering, hardware input
- Audio-focused: DMA-driven I2S output, real-time safe, static allocation only
- 471 unit tests + DSP golden reference suite
Quick Start
Prerequisites: ARM GCC toolchain (arm-none-eabi-gcc)
# Clone the ecosystem
git clone https://github.com/soundbytelabs/sound-byte-libs.git
git clone https://github.com/soundbytelabs/sound-byte-libs-examples.git
git clone https://github.com/soundbytelabs/sbl-hardware.git
# Set environment
export SBL_PATH=/path/to/sound-byte-libs
export SBL_HW_PATH=/path/to/sbl-hardware
# Build for Daisy Seed (STM32H750)
cd sound-byte-libs-examples/hello-blinker
cmake --preset daisy
cmake --build build/daisy
# Flash with dfu-util (hold BOOT, press RESET, release BOOT)
dfu-util -a 0 -s 0x08000000:leave -D build/daisy/hello_blinker.bin
What Can You Build?
SBL scales from trivial to complex, and every byte is accounted for:
- hello-blinker (1KB) – LED blinking on any supported board. Proves the architecture: manifest-driven GPIO, zero-overhead HAL, multi-platform from one source file.
- hello-synth (13KB) – A complete subtractive synthesizer voice. Band-limited PolyBLEP oscillator through a state variable filter and VCA, driven by an ADSR envelope, with MIDI input over UART. Runs on Daisy Pod.
- hello-instrument (24KB) – A polyphonic chord pad instrument with up to 6 SuperSaw voices, stereo SVF filtering, LFO modulation, beat-quantized chord changes, circle-of-fifths navigation, and multi-mode knob mapping with pickup. Also Daisy Pod.
The jump from 1KB to 24KB tells the story: SBL's layered architecture means you only pay for what you use.
Code Example
int main() {
sbl::driver::init();
constexpr auto led = sbl::hw::gpio::status_led;
sbl::driver::Gpio::set_mode(led, sbl::gpio::PinMode::Output);
while (true) {
sbl::driver::Gpio::toggle(led);
sbl::driver::Timer::delay_ms(500);
}
}
Uber-umbrella header for all target-specific code.
Build System
SBL provides optional CMake hooks that simplify build setup. Our examples use them, but you can wire up builds however you prefer.
include($ENV{SBL_PATH}/tools/cmake/SblHooks.cmake)
sbl_pre_project() # Resolves hardware, configures toolchain
project(my_app C CXX ASM)
sbl_post_project() # Finalizes platform setup, creates sbl::driver
add_executable(my_app src/main.cpp)
target_link_libraries(my_app PRIVATE sbl::driver)
sbl_finalize(my_app) # Generates .bin, .hex as needed
When using hooks, they read your target manifest and configure the build accordingly — setting up the ARM toolchain, generating binary outputs (BIN/HEX), and wiring in platform-specific startup code. Override hooks or skip them entirely for custom setups.
Platform Support
| Platform | MCU | Core | Status |
| Daisy Seed | STM32H750 | Cortex-M7 | Primary — full peripheral support |
| Raspberry Pi Pico | RP2040 | Cortex-M0+ | GPIO, Timer, UART, USB CDC |
| Raspberry Pi Pico 2 | RP2350 | Cortex-M33 | GPIO, Timer, UART, USB CDC |
The STM32H7 is the primary development target with full audio support: ADC (polling + DMA scan), DMA, SAI/I2S, and all DSP/widget layers verified on hardware.
Tools
SBL provides four Python tools that work together:
| Tool | Purpose | When Run |
| cecrops | SVD → C++ register headers | Rare (new MCU/peripheral) |
| sloth | Hardware resolution → config headers | Every build (via CMake) |
| lute | Lookup table generation (waveforms, pitch) | When adding/changing tables |
| sbl | Project configuration and utilities | Project setup, queries |
sloth - Hardware Resolution
sloth (Sound Byte Labs Open Tool for Hardware) resolves hardware manifests and generates type-safe C++ headers.
# Resolve and show hardware graph
python -m sloth graph targets/daisy.json
# Generate config headers
python -m sloth generate targets/daisy.json -o build/generated
# Query MCU info (used by CMake hooks)
python -m sloth resolve targets/daisy.json --print-mcu-name
cecrops - Register Generation
cecrops generates C++ register definitions from CMSIS-SVD files with manifest-driven configuration and integrated patching for SVD errata.
# Generate register headers from SVD
python -m cecrops generate sbl-hardware/mcu/arm/stm32h750
# Show SVD file info
python -m cecrops info path/to/file.svd
Each MCU using cecrops has a cecrops.json manifest defining SVD source, output peripherals, and patches. See FDP-009 for design details.
sbl - Project CLI
sbl provides project configuration and utility commands.
# Initialize a new SBL project
python -m sbl_cli init my-project --target daisy
# Show project info
python -m sbl_cli info
Repository Structure
sound-byte-libs/
├── src/sbl/ # Library source
│ ├── hal/ # Layer 1: Hardware abstraction + convenience
│ ├── primitives/ # Layer 2: Buffers, containers, math, IO
│ ├── dsp/ # Layer 3: DSP atoms (phase, filters, LUTs)
│ ├── patterns/ # Layer 3: Timing, synchronization
│ ├── components/ # Layer 4: CV, controls, display
│ ├── midi/ # Layer 4: MIDI parser + input
│ ├── usb/ # Layer 4: USB CDC
│ ├── widgets/ # Layer 5: Sources, processors, modulators
│ ├── log/ # Logging system
│ ├── validation/ # SFINAE contract validation
│ └── common/ # Shared constants
├── tools/ # sloth, lute, cmake hooks, sbl-cli
├── sbl-schema/ # Pydantic models → JSON schemas
├── test/ # 471 C++ tests, 53 Python tests
└── docs/ # Architecture, hardware system, guides
Examples (separate repository)
sound-byte-libs-examples/
├── hello-blinker/ # LED blinking (multi-platform)
├── hello-uart/ # Debug serial output
├── hello-adc/ # ADC DMA scan + CvInput smoothing
├── hello-dma/ # DMA memory transfer
├── hello-audio/ # SAI/I2S audio + knob-controlled pitch
├── hello-usb-cdc/ # USB virtual serial port
├── hello-controls/ # Buttons, encoder, LEDs, pots (Daisy Pod)
├── hello-synth/ # Subtractive synth voice with MIDI (Daisy Pod)
├── hello-instrument/ # Polyphonic SuperSaw chord instrument (Daisy Pod)
├── hello-i2c/ # I2C bus scanner (Daisy Seed)
└── hello-pwm/ # SoftPwm BCM LED driver (Daisy Pod)
Documentation
Design Philosophy
- Bare metal first - No vendor HALs, SVD-generated registers
- Every byte matters - We celebrate small binaries
- Audio timing - Designed for real-time constraints
- Cross-vendor - Avoid platform lock-in
- Templates for performance - Clean APIs, zero runtime overhead
License
Copyright (c) 2025 Michael Skiles. See LICENSE file.