Library / SDK
sensorium/Mozzi avatar
sensorium/Mozzi

Mozzi: sound synthesis on a microcontroller without a shield

sound synthesis library for Arduino

1,293 stars207 forksCLGPL-2.1

At a glance

What is it?
Mozzi is a C sound synthesis library for Arduino and other microcontrollers, giving you oscillators, envelopes, filters and delays on boards as small as an Uno, with PWM, PDM, DAC and I2S output modes. It suits an installation artist or an electronics hobbyist who wants interactive sound from a cheap board, and the 2.0 line brought a porting break that catches people out.
Who is it for?
Mozzi suits a maker building an installation, a sonification or an interactive instrument on a microcontroller, who wants synthesis units rather than a fixed sample player and who can pick the output mode that matches their board. It does not suit a project that needs polyphonic music playback with reliable timing, since the design is a per sample callback on a single audio stream, and it does not suit someone upgrading from 1.x who cannot port their sketch.
Can I use it commercially?
Yes, with conditions. LGPL-2.1 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 93 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Synthesis units instead of a beep

Mozzi is a sound synthesis library for Arduino, and the README opens with a joke that lands on the point. It says that currently your Arduino can only beep like a microwave oven, and that Mozzi brings it to life by producing more complex growls, sweeps and chorusing atmospherics. The sounds are constructed from familiar synthesis units, oscillators, delays, filters and envelopes.

The stated use cases are algorithmic music for an installation or a performance, and interactive sonifications of sensors. The pitch of the project is deliberately small hardware, an Arduino that is small, modular and super cheap, without additional shields, without message passing and without an external synth. That last list is the requirement set, and it explains the design of the whole library.

The feature list is worth reading for the details it exposes. There is a useful audio toolkit of oscillators, samples, lines, envelopes, scheduling and filtering. The sample rate is configurable, usually in powers of two such as 16384 Hz or 32768 Hz, and the control rate is variable from 64 Hz upwards. The output modes are several, including 16 bit output to an external DAC, and the library allows interfacing to custom output routines, with examples for playing audio on external DAC modules and even bluetooth. There are readymade wavetables and a script to convert your own sound files. And there are fast ADC and other cpu-efficient utilities, because on an Uno the CPU budget is the real constraint.

The licence is LGPL-2.1, with the licence files at the top of the repository.

The sketch template shows the whole programming model

The template for an empty Mozzi sketch is the most useful thing in the README, because it shows the entire programming model in a dozen lines.

c
#include <Mozzi.h>   // at the top of your sketch

void setup() {
	startMozzi();
}

void updateControl(){
	// your control code
}

AudioOutput_t updateAudio(){
	MonoOutput::from16Bit( [my_cool_sample] );
}

void loop() {
	audioHook();
}

Three functions, and each one has a distinct job. The audio callback, updateAudio, runs at the sample rate and produces one output sample, and it returns an AudioOutput_t so the same code works whether the target is 8 bit PWM or a 16 bit DAC. The control callback, updateControl, runs at the control rate, which is the slower rate at which parameters are updated, and that separation is what lets a slow control loop drive a fast audio stream without the audio glitches. The main loop does nothing but call audioHook, which is the call that services both callbacks, so your own loop code is free to do other work as long as it does not block for long.

The result is a cooperative real time model, and the whole library is built around the assumption that updateAudio must return quickly every sample period. That is a design constraint you inherit whether you like it or not, and it is the reason the library includes cpu-efficient utilities, the rolling average and rolling statistics headers, and the CapPoll and RCpoll helpers for sampling sensors without stalling the audio.

The repository layout makes the building blocks visible. Oscil.h, MetaOscil.h, Phasor.h and WavePacket.h are the oscillator family. ADSR.h and Ead.h are envelope generators. LowPassFilter.h, ResonantFilter.h, PDResonant.h and StateVariable.h are filters. AudioDelay.h, AudioDelayFeedback.h, ControlDelay.h and EventDelay.h are the delay lines. Sample.h, SampleHuffman.h and WavePacketSample.h handle sample playback. There are utility headers too, AutoMap.h, AutoRange.h, IntMap.h, Smooth.h, Stack.h, and a ReverbTank.h for a reverb effect. The C++ file mozzi_fixmath.cpp and the meta.h header hold the fixed point arithmetic that lets this run on an 8 bit AVR without a floating point unit.

One library across a wide range of microcontrollers

The board support is the feature that makes Mozzi unusual among Arduino libraries. The README lists availability for a wide and growing range of MCUs, with and without inbuilt DACs, naming Arduino Uno R3 and R4, STM32, Teensy, ESP8266, ESP32, Raspberry Pi Pico, CH32 and more.

That range spans three very different architectures, and the table in the README shows the output mode and default pins for each. The ATmega328 and 168 family, which covers the Uno, Nano, Pro Mini, Duemilanove and Leonardo, uses one pin PWM mode on pin 9 as the default with a second pin in parentheses for stereo. The ATmega2560 family, which is the Mega and the EtherMega, defaults to pin 11. The SAMD boards, which is the Nano 33 IoT, the Adafruit Playground Express and the Gemma M0, use the inbuilt DAC on A0 with a speaker. The Renesas Arduino Core, which is the Uno R4, also uses an inbuilt DAC on A0. The ESP8266 defaults to PWM on GPIO2, the ESP32 variants default to pins 15 and 16, and the RP2040, which is the Raspberry Pi Pico, defaults to pins 0 and 1. The CH32, a RISC-V part, uses PA6.

Each row lists the available output modes and the default one in bold, and the table explicitly says it is not necessarily complete, with the hardware section of the API documentation holding platform specific notes and pin configuration options.

Two entries in the table carry warnings that are worth heeding. The ESP8266 and ESP32 rows both say to beware of erratic or vastly different pin labels across board variants, which is a real trap when the same sketch is moved between ESP32 boards.

Output modes decide how much audio quality you get

The output mode is the single most consequential setting in Mozzi, and the table legend defines them by the macro you compile with.

PWM-1 is one pin PWM mode, MOZZI_OUTPUT_PWM, and PWM-2 is two pin PWM mode, MOZZI_OUTPUT_2PIN_PWM. PDM is pulse density modulation, and it may be either MOZZI_OUTPUT_PDM_VIA_SERIAL or MOZZI_OUTPUT_PDM_VIA_I2S, depending on whether your board has a serial or an I2S interface. The inbuilt DAC mode is MOZZI_OUTPUT_INTERNAL_DAC, and native support for externally connected I2S DACs is MOZZI_OUTPUT_I2S_DAC, which is never the default because it needs several pins and they are often configurable. The legend also notes that all platforms support external output modes, MOZZI_OUTPUT_EXTERNAL_TIMED or MOZZI_OUTPUT_EXTERNAL_CUSTOM, which allow connecting DACs or other external circuitry.

The pattern across the table is clear. A board with an inbuilt DAC gets the inbuilt DAC mode by default, which is the highest quality option available without adding hardware. A board without one falls back to two pin PWM, which uses two pins to push a higher resolution signal than a single pin can carry. And any board can be pushed further with an external DAC over I2S or through a custom output routine, which is where the 16 bit output mode fits.

That is why the quick start wiring instruction is specific. You wire a 3.5mm audio jack with the centre to the audio out pin and the shield to GND on the Arduino, plug into a computer, and listen with a sound program like Audacity, or connect any other high impedance input such as an active speaker. The mention of a high impedance input is the practical detail, because an Uno's PWM output cannot drive a speaker directly without amplification.

Mozzi 2.0 broke source compatibility and says so

The section about users coming from Mozzi 1.x is short and blunt, and it is worth reading before anything else. Mozzi 2.0 brings a lot of changes under the hood and is not 100 percent source compatible with earlier versions. Most sketches should continue to compile, but with a lot of warnings. A few others will no longer work. The documentation points at a Porting to Mozzi 2.0 page for what to change.

The escape hatch is offered too. There is still a Mozzi_1 branch in the git repository containing the last stable version of 1.x, with packages for that version on GitHub at the 1.1.2 tag, and the documentation says that branch will not get any new development and that users still on those versions are encouraged to migrate to 2.

The release naming in this project is unusual and worth knowing. The versions are tagged with a 2.0 series and each one carries a binomial name, so v2.0.4 is Anopheles wellcomei, v2.0.3 and v2.0.2 carry the same name. The pattern is a species name for each minor version and a separate name for each patch, and it means the version string alone does not tell you much about the changes, so the release notes are where the detail is.

The version history shows v2.0.2 in February 2025, v2.0.3 in January 2026 and v2.0.4 in April 2026, and the last push to master was on 2026-07-22. So the library is being worked on, but the release train is slow relative to the commits, and a project that pins a version pins a fairly old snapshot of the work.

Where Mozzi is the wrong tool

Three cases argue against it. The first is a project that needs to play music. Mozzi is a synthesis engine, and the model is a callback that returns one sample at a time, which suits generating sound and sonifying sensor data. Playing a multi track piece with accurate timing and polyphony is a different problem, and there are dedicated libraries for it. If you want a sound effect triggered once, a sample player is smaller and simpler.

The second case is a board you do not control the pins of. The output mode and the pins are compile time choices with a table of defaults per board, and the ESP32 rows in that table carry explicit warnings about vastly different pin labels across board variants. On a board with a crowded pin map, a fixed default can land on something you needed, and the hardware section of the API documentation is where the per platform overrides live.

The third case is a 1.x sketch you cannot port. The documentation is direct that a few sketches will not work on 2.0, and the Mozzi_1 branch is explicitly frozen, so staying on it means staying on a version that receives nothing further.

There is a real time constraint underneath all of this that is worth internalising. The audio callback has to return within the sample period, 16384 Hz or 32768 Hz, which is 61 or 31 microseconds, and the control callback runs at 64 Hz or above on a chip that may have no floating point unit, which is why the fixed point arithmetic in mozzi_fixmath.cpp exists at all. On an ATmega328 at 16 MHz that is a very tight budget, and the reason the library ships cpu-efficient ADC helpers is that a blocking analog read in the wrong place will not just add noise, it will glitch the audio. The library is a good fit for the small board it was written for, and the CPU budget is the price of that.

Editorial conclusion

Mozzi suits a maker building an installation, a sonification or an interactive instrument on a microcontroller, who wants synthesis units rather than a fixed sample player and who can pick the output mode that matches their board. It does not suit a project that needs polyphonic music playback with reliable timing, since the design is a per sample callback on a single audio stream, and it does not suit someone upgrading from 1.x who cannot port their sketch. Before you start, read the Porting to Mozzi 2.0 guide, check the pin table for your exact board and output mode, and note that the last push was on 2026-07-22 with the newest release v2.0.4 from 2026-04-14.

Frequently asked questions

How do I install Mozzi?

The easiest route is the Arduino Library Manager: Arduino, then Sketch, then Include Library, then Library Manager, type Mozzi into the search field and click install. Other methods, including the development version, are described on the project's download page.

What are updateControl and updateAudio in a Mozzi sketch?

updateAudio is the audio callback that runs at the sample rate and returns one output sample as an AudioOutput_t, while updateControl runs at the variable control rate to update parameters. The main loop calls audioHook, which services both callbacks.

Which output modes does Mozzi support?

One pin PWM, two pin PWM, PDM over serial or I2S, the inbuilt DAC, and native I2S DAC support, selected with the MOZZI_OUTPUT_ macros. Every platform also supports external output modes, MOZZI_OUTPUT_EXTERNAL_TIMED and MOZZI_OUTPUT_EXTERNAL_CUSTOM, for connecting a DAC or other external circuitry.

Is Mozzi 2.0 compatible with sketches written for Mozzi 1.x?

Not entirely. The README states that Mozzi 2.0 is not 100 percent source compatible, that most sketches should compile with a lot of warnings, and that a few will no longer work, with a Porting to Mozzi 2.0 guide covering the changes. A frozen Mozzi_1 branch and 1.1.2 packages are available but will not get new development.

Official sources

  1. License: LGPL-2.1
  2. Project website
  3. README
  4. Releases
  5. sensorium/Mozzi on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sensorium-mozzi.svg)](https://hysenlabs.com/projects/sensorium-mozzi)

Was this useful?