# DawDreamer renders audio processor graphs from Python

> DawDreamer is a C++ and Python digital audio workstation framework built on JUCE and nanobind, with VST, VST3 and FAUST processors, MIDI, time-stretching and parameter automation. It suits researchers and developers who need deterministic offline rendering, and it is a headless engine rather than a DAW interface.

**DBraun/DawDreamer** — Digital Audio Workstation with Python; VST instruments/effects, parameter automation, FAUST, JAX, Warp Markers, and JUCE processors

- Repository: https://github.com/DBraun/DawDreamer
- Website: http://dirt.design/DawDreamer/
- Stars: 1,344 · Forks: 101
- Language: C++
- License: GPL-3.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/dbraun-dawdreamer

## A JUCE engine with a nanobind Python surface

DawDreamer is an audio-processing Python framework supporting core DAW features and beyond. The foundation is JUCE, with a user-friendly Python interface thanks to nanobind. The project description calls it a digital audio workstation with Python, and the primary language of the repository is C++.

That layering explains a lot about the design. JUCE is the established C++ audio framework that DawDreamer builds on. DawDreamer does not reinvent that; it wraps it and adds the parts a script needs: a graph of processors, offline rendering, MIDI, automation, and the plugin formats that ship as compiled binaries rather than as Python.

The project is not new. The README points to an introduction paper presented as a Late-Breaking Demo at the 2021 ISMIR Conference, and the arXiv link, 2111.09931, is the citation for the design. DawDreamer evolved from an earlier VSTi audio renderer called RenderMan, which is the ancestor for anyone who has used that tool.

The feature list in the README is long but it is a list of things a script normally cannot do. Composing graphs of multi-channel audio processors, audio playback, VST instruments and effects with UI editing and state loading and saving, FAUST effects and polyphonic instruments, time-stretching and looping optionally according to Ableton Live warp markers, pitch-warping, parameter automation at audio-rate and at pulses-per-quarter-note, parameter automation saving in absolute audio-rate time, MIDI playback in absolute time and PPQN time, MIDI file export in absolute time, rendering and saving multiple processors simultaneously, support for the Faust Box and Signal APIs, transpiling Faust code to JAX and Flax and other target languages such as C++, Rust and Wasm, machine learning experiments with QDax, and multiprocessing support.

## The Faust example shows the whole render cycle in twenty lines

The README's first example is runnable as-is, and it shows the shape of the API. A RenderEngine is created with a sample rate and a block size, a Faust processor is made, its DSP source is set as a string, parameters are set, the graph is loaded, and the engine renders.

```python
import dawdreamer as daw
from scipy.io import wavfile
SAMPLE_RATE = 44100
engine = daw.RenderEngine(SAMPLE_RATE, 512)  # 512 block size
faust_processor = engine.make_faust_processor("faust")
faust_processor.set_dsp_string(
    """
    declare name "MySine";
    freq = hslider("freq", 440, 0, 20000, 0);
    gain = hslider("vol[unit:dB]", 0, -120, 20, 0) : ba.db2linear;
    process = freq : os.osc : _*gain <: si.bus(2);
    """
    )
print(faust_processor.get_parameters_description())
engine.load_graph([
                   (faust_processor, [])
])
faust_processor.set_parameter("/MySine/freq", 440.)  # 440 Hz
faust_processor.set_parameter("/MySine/vol", -6.)  # -6 dB volume

engine.set_bpm(120.)
engine.render(4., beats=True)  # render 4 beats.
audio = engine.get_audio()  # shaped (2, N samples)
wavfile.write("sine_demo.wav", SAMPLE_RATE, audio.T)
```

Two details are worth noticing. The block size is a constructor argument, 512 in this example, which is a signal-processing parameter rather than a UI setting. And render takes beats=True, so the length can be given in musical time against the tempo set with set_bpm, which is what makes the PPQN automation mode coherent.

The last three lines show the re-render loop that is the actual point of the framework: change a parameter, render again, compare. The README's example changes the frequency to 880 and renders again.

Parameters are addressed by a path string, such as "/MySine/freq", and get_parameters_description prints the parameter list, which is how you discover what is available on a Faust processor or a plugin.

## Plugin graphs connect processors by name, with per-processor capture

The second README example covers the VST path, and the API shape is different in one important way. A plugin processor is made from a path to a shared library, and the graph is described as a list of tuples where the second element lists the processors feeding it.

```python
engine = daw.RenderEngine(SAMPLE_RATE, 512)
engine.set_bpm(120.)

synth = engine.make_plugin_processor("synth", INSTRUMENT_PATH)
print("inputs:", synth.get_num_input_channels())
print("outputs:", synth.get_num_output_channels())
print(synth.get_parameters_description())

synth.set_parameter(7, .1234)

# (MIDI note, velocity, start sec, duration sec)
synth.add_midi_note(60, 100, 0.0, 2.)

# optionally capture intermediate audio
synth.record = True

effect = engine.make_plugin_processor("effect", EFFECT_PATH)

engine.load_graph([
  (synth, []),
  (effect, [synth.get_name()])  # effect needs 2 channels, and "synth" provides those 2.
  ])

engine.render(4.)  # render 4 seconds.
audio = engine.get_audio()
wavfile.write("synth_demo_wet.wav", SAMPLE_RATE, audio.T)
synth_audio = engine.get_audio("synth")
wavfile.write("synth_demo_dry.wav", SAMPLE_RATE, synth_audio.T)
```

The graph is a list of (processor, inputs) pairs, where inputs name the processors that feed it. That is a data structure rather than a call sequence, which means the audio routing is inspectable and can be generated programmatically.

The record flag is the feature that makes this useful for research. Setting synth.record = True and then calling engine.get_audio("synth") returns the signal at that node, so a dry signal and a wet signal can be written out and compared. For a research pipeline that is a requirement rather than a convenience.

Plugin parameters are addressed by index, with set_parameter(7, .1234), while Faust parameters are addressed by path. Plugin channels are queryable with get_num_input_channels and get_num_output_channels, which is what lets you check the assumption in the comment that the effect needs two channels and the synth provides them.

## Import dawdreamer before JAX or the process can segfault

The known issues section documents one problem that has its own subsection, and it is the first thing to check if you plan to combine DawDreamer with machine learning tools.

DawDreamer must be imported before JAX or other LLVM-based libraries, such as PyTorch with TorchScript or Numba, to avoid LLVM initialization conflicts that can cause segmentation faults:

```python
# CORRECT:
import dawdreamer as daw  # Import DawDreamer first!
import jax

# WRONG - May cause segfault:
import jax
import dawdreamer as daw  # Importing after JAX can crash!
```

The reason given is that both DawDreamer, through Faust's LLVM backend, and JAX use LLVM internally. When JAX initializes LLVM first, for example by calling jax.devices(), importing DawDreamer afterward can cause conflicts in LLVM's global state, resulting in a crash. The stated workaround is to always import dawdreamer at the top of your Python file, before any JAX or related libraries.

This is a genuine constraint on how you structure the code, and it is the kind of thing that is invisible until it segfaults in a notebook. The escape is the documented import order, which works because the ordering is under your control, but the reason it is easy to get wrong is that people usually import the library they think of as primary first, and in a research script that is often the ML framework.

There is a second side to it. The README's feature list includes transpiling Faust code to JAX and Flax, and machine learning experiments with QDax, with an examples/Faust_to_JAX directory and an examples/Faust_to_QDax directory. The project is explicitly designed for the intersection of audio and machine learning, so the import order conflict is a known cost of that intersection rather than an accident.

## Installation needs 64-bit Python 3.11 to 3.14 on all three platforms

The install path is a single command, and the platform requirements are spelled out.

```bash
pip install dawdreamer
```

The macOS requirements are 64-bit Python 3.11-3.14, Apple Silicon (arm64) or Intel (x86_64), and macOS 11.0 or higher. Windows needs an x86_64 CPU and 64-bit Python 3.11-3.14. Linux needs an x86_64 or aarch64 CPU and 64-bit Python 3.11-3.14. The README also lists full support on macOS, Windows, Linux, Google Colab, and an Ubuntu Dockerfile.

The Google Colab support is a hint about the intended use. Colab is where you run a notebook that needs a GPU for the model side and audio rendering for the data side, and it is not an environment where you can compile JUCE. That DawDreamer ships wheels for that environment says something about the project's priorities.

The build machinery in the repository explains the rest. The setup.py reads the version out of DawDreamer.jucer, the JUCE project file, and writes a dawdreamer/_version.py, and it builds libsamplerate and downloads libfaust from thirdparty/libfaust. The Dockerfile does the same inside a manylinux_2_34_x86_64 image, installing the X11, ncurses, freetype and alsa development packages, building libsamplerate with cmake, then building DawDreamer from Builds/LinuxMakefile and copying libdawdreamer.so into the Python package directory.

The project is therefore a compiled extension with a Python wrapper, not a pure Python package. That is why the platform matrix is explicit.

## GPL-3.0, a v0.9 release, and a repository that keeps its research artifacts

The licence is GPL-3.0, with the LICENSE file in the repository as the authoritative text, and this is a licensing statement rather than legal advice. For a project that links JUCE and hosts VST plugins, GPL-3.0 is the licence that makes distribution obligations explicit, and it matters more here than for a typical library.

The version record shows recent movement. v0.9.0 was released on 2026-08-12, before that v0.8.3 on 2024-09-09 and v0.8.0 on 2023-11-17, and the last push was on 2026-10-02. The repository is not archived, and the sub-1.0 version number is consistent with a research framework that is still changing shape.

The repository layout is unusually rich in research artifacts. There is an examples/ directory with Box_API, Faust_to_JAX, Faust_to_QDax, dj_mixing, mashup_generator, multiprocessing_plugins and xml_synth_sound_rendering. There are docs/, tests/, Builds/, Source/, thirdparty/, a Dockerfile, a CITATION.cff for citation, a PICKLE_FORMAT.md documenting the serialization format, an AGENTS.md, a CHANGELOG.md and a DEVELOPER.md.

The examples are the clearest statement of intent. A mashup generator, DJ mixing and XML synth sound rendering are not the things a conventional DAW is built for; they are the things a researcher building an automated audio system needs. The example set also tells you the maturity level of each area, since a mashup generator and a QDax integration are not equally polished.

The project also keeps a.clang-format file, a.pre-commit-config.yaml, and a ruff configuration in pyproject.toml targeting Python 3.11 with a line length of 100, with per-file ignores for the star imports in the Faust API and the test helpers.

## Conclusion

Adopt DawDreamer if your work is scripted audio, meaning batch rendering, parameter sweeps, or an audio machine learning pipeline that needs a deterministic engine behind a Python API. Do not adopt it as a DAW, because it has no timeline or editor interface, and it will not help you if you need to record live input. Before you install, confirm you are on 64-bit Python 3.11 to 3.14, and if your code also uses JAX, PyTorch TorchScript or Numba, import dawdreamer before those libraries or the shared LLVM state can crash the process.

## FAQ

### How do I install DawDreamer and what are the requirements?

Install it with pip install dawdreamer from PyPI. You need 64-bit Python 3.11 to 3.14 on macOS, Windows or Linux, and on macOS version 11.0 or higher, with either Apple Silicon or Intel. The README also lists support for Google Colab and an Ubuntu Dockerfile.

### How do I avoid a segfault when using DawDreamer with JAX?

Import dawdreamer before JAX or any other LLVM-based library such as PyTorch with TorchScript or Numba. The README explains that both DawDreamer, through Faust's LLVM backend, and JAX use LLVM internally, so importing DawDreamer after JAX initialises LLVM can conflict in LLVM's global state and crash the process.

### How do I render audio from a VST instrument and an effect in DawDreamer?

Create a RenderEngine with a sample rate and block size, make plugin processors from the paths to the plugin binaries, and load a graph of (processor, inputs) pairs where inputs name the processors feeding each one. Then call engine.render with a duration, and use engine.get_audio to retrieve the output or the signal at a specific node.

### Does DawDreamer have a timeline or editor interface?

No. The README describes it as an audio-processing Python framework supporting core DAW features, and the examples are scripting tasks such as mashup generation, DJ mixing and XML synth sound rendering rather than interactive editing. The API is a render engine driven from Python.

### What licence is DawDreamer released under?

GPL-3.0, with the LICENSE file in the repository as the authoritative text. This is a licensing statement rather than legal advice, and the licence matters more than usual because the project links JUCE and hosts third-party VST plugins.

## Sources

- [DBraun/DawDreamer on GitHub](https://github.com/DBraun/DawDreamer)
- [License: GPL-3.0](https://github.com/DBraun/DawDreamer/blob/main/LICENSE)
- [Project website](http://dirt.design/DawDreamer/)
- [README](https://github.com/DBraun/DawDreamer/blob/main/README.md)
- [Releases](https://github.com/DBraun/DawDreamer/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dbraun-dawdreamer
