ken

STM32 Polyphonic Synth: Bare-Metal DSP

8-Voice Polyphonic Wavetable Synthesizer on Cortex-M4

BoardSTM32F407G Discovery
OLEDSSD1306
PWM DriverPCA9685
Analog MuxTC74HC4052

Overview

Having learned the basics of audio development in embedded systems, I wanted to strip away the layers of abstraction and explore bare-metal programming. While the Teensy and Daisy ecosystems provide excellent platforms to get audio output quickly, their libraries hide much of the underlying hardware logic.

To truly understand the fundamental structures needed for low-level DSP, I pivoted to STM32 development. I chose the STM32F407G Discovery board: a dev kit featuring an onboard DAC and line-out. My end goal was to create an 8-voice polyphonic wavetable synth, heavily inspired by hardware like the Roland System 1m. This required implementing professional-grade audio features, including zero-delay feedback filters and DMA-driven audio, all while managing the strict timing constraints of a 168MHz ARM Cortex-M4 processor.

STM32 Synth Hardware Setup
STM32F407G Discovery board, SSD1306 OLED, and potentiometer bank with an analog multiplexer.

The Architecture

The system is built on a non-blocking pipeline that strictly separates hardware UI control from the synthesis engine. To ensure continuous, glitch-free audio, the DSP engine utilizes a Circular Buffer alongside DMA (Direct Memory Access).

Memory & Performance Optimization

A major technical hurdle in bare-metal audio is avoiding bus contention between the CPU and the DMA controller. By placing the VoiceManager and the active synthesis objects into CCMRAM (Core Coupled Memory), the CPU can execute complex floating-point math at maximum speed without having to wait for the main system bus.

FeatureImplementationBenefit
Audio TransportDMA via I2SZero CPU overhead for audio data transfer
Wavetable SynthesisCCMRAMInstant memory access for heavy float math
Control RateTimer InterruptsJitter-free ADC multiplexer scanning
UI RenderingI2C Fast ModeSmooth, non-blocking OLED visual updates

Problem USB MIDI Class Compliance

Standard STM32 HAL libraries provide generic USB templates, but do not include a 'plug-and-play' MIDI class.

Solution:

Modified the USB Device Middlewares to implement custom MIDI descriptors, allowing the board to be instantly recognized as a standard MIDI controller by any DAW.

Problem Filter Instability vs. CPU Load

Initial experiments with a digital Moog Ladder filter simulation proved too computationally heavy for the MCU to run 8 voices simultaneously.

Solution:

Implemented a Zero-Delay Feedback (ZDF) State Variable Filter. By mathematically solving the algebraic loop at every sample, it achieves analog-style stability at high resonance while remaining computationally efficient.

The Synthesis Engine

The core synthesis engine features two oscillator slots per voice, allowing for Real-Time Wavetable Morphing. By interpolating between two distinct wavetables based on ADC inputs, the user can create evolving, complex timbres that are then shaped by an ADSR envelope and routed through the ZDF filter.

Outcomes

01

Hard Real-Time Performance

Optimized the DMA circular buffer for hyper-low latency audio, ensuring the synth responds instantly to incoming USB MIDI without audio dropouts.

02

Advanced Memory Optimization

Leveraged the STM32's 64KB CCMRAM to host the DSP engine, allowing the Cortex-M4 to process complex math without fighting the DMA for memory access.

03

Analog-Modeled Stability

Successfully deployed Zero-Delay Feedback (ZDF) filters that remain mathematically stable and musical, even when pushed into extreme self-oscillation.

04

Professional Voice Management

Developed a robust 8-voice polyphony engine with 'Soft-Kill' logic, preventing audible clicks and DC offsets during rapid note stealing.

05

Custom USB Class Compliance

Rewrote low-level USB descriptors from scratch, turning a generic development board into a plug-and-play studio instrument.

Future Work