stm32h7

12 Mar 2026
embedded systems

STM32H755 Granular Synthesizer

A real-time granular synthesizer running on the Cortex-M7 core of an STM32H755 dual-core MCU. Audio streams in and out over USB (UAC2 + MIDI composite device), with a browser-based control panel for parameter tweaking and monitoring.

What It Does

PC audio (YouTube, a DAW, anything) routes through the STM32 via USB Audio. The firmware captures incoming audio into a circular source buffer, then a 32-voice granular engine chops it into tiny overlapping grains with controllable density, size, spray, speed, and stereo spread. An FX chain (filter, ping-pong delay, Freeverb reverb) processes the output before sending it back to the PC over USB. A web UI provides sliders, transport controls, file playback, recording, and real-time performance telemetry.

Hardware

  • Board: NUCLEO-H755ZI-Q (STM32H755ZIT6, Cortex-M7 @ 480 MHz)
  • USB Audio/MIDI: CN13 (user USB port) — not the ST-LINK port
  • Display: SSD1306 128x64 OLED via I2C1 (PB8/PB9)
  • Power: SMPS only — do NOT configure for LDO or the board bricks

Features

  • Granular engine: 32 simultaneous grains, Hann windowing, zero-crossing grain start, bipolar speed (-2x to +2x with reverse), speed scatter/randomize
  • FX chain: Biquad LPF → stereo ping-pong delay (500ms max) → Freeverb
  • USB composite device: UAC2 stereo 48 kHz/16-bit (in + out) + MIDI
  • Web control panel: Real-time sliders, keyboard shortcuts, file playback, recording, preset import/export, performance telemetry
  • OLED display: Grain visualization, CPU usage, active grain count
  • Telemetry: 10 Hz MIDI CC stream with CPU %, active grains, peak/RMS levels, buffer stats

Architecture

PC Audio ──→ USB OUT ──→ Source Buffer (AXI SRAM, 250K samples)
                              │
                              ▼
                     32-voice Granular Engine
                              │
                              ▼
                    FX: LPF → Delay → Reverb
                              │
                              ▼
              USB IN ──→ PC Speakers (via PulseAudio loopback)
                              │
                              ▼
                     Web UI ←── MIDI CC telemetry

Memory Layout

Region Address Size Usage
FLASH 0x08000000 1 MB Firmware code
DTCM 0x20000000 128 KB Stack, BSS, static data
AXI RAM 0x24000000 512 KB TinyUSB buffers + source buffer
SRAM1 0x30000000 128 KB DMA buffers (OLED I2C)
SRAM2 0x30020000 128 KB Delay line buffers (int16)
SRAM3 0x30040000 32 KB Reverb comb/allpass buffers

Source Files

File Purpose
src/main.c Superloop, USB callbacks, DWT profiling, telemetry, OLED
src/granular.c 32-voice granular engine
src/fx.c FX chain: biquad LPF, ping-pong delay, Freeverb
src/ssd1306.c SSD1306 OLED driver (DMA + polling)
src/i2c.c I2C1 peripheral driver
src/usb_descriptors.c USB Audio + MIDI composite descriptor
src/system_stm32h7xx.c Clock tree, PLL, SMPS power config
web/index.html Browser control panel (Web MIDI API)

Build & Flash

Requires Docker (the toolchain runs in a container).

# Build and flash
docker compose run --rm dev /workspace/scripts/flash.sh

# USB must be on CN13 (user USB), not the ST-LINK port

The flash script builds with CMake + Ninja using arm-none-eabi-gcc, then flashes via OpenOCD.

Audio Routing

After flashing, set up PulseAudio loopback routing and the web server:

./scripts/audio-setup.sh           # set up routing + start web server
./scripts/audio-setup.sh --teardown # undo everything

This configures:

  1. STM32 as the default PulseAudio sink (all PC audio routes through it)
  2. Loopback from STM32 source back to PC speakers
  3. Web server on http://localhost:8000

Web UI

Open http://localhost:8000 in Chrome (requires Web MIDI API support).

  • Auto-connects to the Granular Synth MIDI device
  • Transport: Record, Test Tone, File Playback, Loop
  • Parameter sliders with click-to-edit values
  • Keyboard shortcuts: Space (record), T (tone), P (play), S (stop), L (loop), Esc (stop all)
  • Performance panel: CPU %, active grains, L/R level meters
  • Preset import/export (JSON)

MIDI CC Map (Channel 1)

CC Parameter Range
1 Grain Density 1–200 Hz
2 Grain Size 10–1000 ms
3 Spray 0–100%
4 Speed -2.0x to +2.0x
5 Scan Position 0–100%
7 Volume 0–100%
8 Dry/Wet 0–100%
10 Stereo Spread 0–100%
12 Randomize 0–100%

[README truncated]

Recent Activity

  • 4cbaf8f reverb working nicely (2026-03-12)
  • 1e14c82 added readme (2026-03-12)
  • 1721a43 added fx see to work coul ddo with more testing (2026-03-11)
  • 0c0c91b reverse grain playback with bidirectional speed slider.. (2026-03-11)
  • d6af94b grain visulaiser working beautifully (2026-03-11)

Languages

  • C: 51%
  • HTML: 24%
  • Assembly: 19%
  • Shell: 4%
  • CMake: 1%