Library / SDK
libpd/libpd avatar
libpd/libpd

libpd: Pure Data's synthesis engine packaged as a library you can link

Pure Data embeddable audio synthesis library

1,252 stars292 forksObjective-CNOASSERTION

At a glance

What is it?
libpd takes Pd Vanilla and wraps it as an embeddable audio synthesis library with a C core and glue for C++, C#, Java, Objective-C and Python, built from a git checkout with submodules rather than a download. It exposes Makefile options that decide whether utilities, extra externals, multiple instances and double precision are compiled in, and it publishes no GitHub releases.
Who is it for?
Adopt libpd if you want the Pure Data patching environment inside an application of your own, a game, a teaching tool, an installation, and you are prepared to build it from a git checkout, because the ZIP download is broken by design and the submodule is the whole point.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 33 days ago.
What is it written in?
Mainly Objective-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

Pd Vanilla as a library, with all that implies

libpd is Pure Data as an embeddable audio synthesis library, and the copyright line reads Peter Brinkmann and the libpd team 2010-2026, so this is a long-running project rather than a recent experiment.

What Pure Data brings is a patching environment for sound: a graph of objects connected by signal and control cables, with a language for writing new objects, and a small set of primitives that make audio behave like audio. Embedding that means a program can build and run patches at runtime, so the patch becomes part of the application's behaviour rather than a file the user opens in an editor.

The mechanism is visible in the repository layout. The `pure-data` directory contains the sources of Pd Vanilla and its standard externals, and it is a git submodule of Miller Puckette's official Pd git repository. The `libpd_wrapper` directory contains the source files that make up the core of libpd, which is the layer that turns Pd's internals into something a host program can drive. The `cpp`, `csharp`, `java`, `jni`, `objc` and `python` directories are the glue for using libpd from those languages.

The consequence of building on a submodule is the one thing to internalise before anything else. You are not embedding a small library that a team wrote for the purpose. You are embedding Pd Vanilla, with libpd's modifications, at whatever version the submodule points to. Every quirk of Pd's internals is inherited, and so is the maintenance relationship with an upstream project that moves on its own schedule.

The intended user is a developer building something interactive with sound: a game with a procedural soundtrack, an installation, a teaching tool for audio programming, a hardware product with a soft synth inside. The licence is recorded as other, a custom licence that GitHub cannot classify, with the text in `LICENSE.txt`, and the last push to `master` was on 2026-09-20. There are no GitHub releases.

The submodule is not optional, and the ZIP download is broken

The README is unusually insistent about how to get the code, and the reason is a concrete failure rather than a preference.

The preferred method to download libpd is to use git, and the README says in bold not to download libpd as a zip or tar.gz file from GitHub. The explanation is mechanical. GitHub does not include submodule files when compiling zip files, so the zip is missing the main pd source files and you will not be able to build libpd, with errors such as *No rule to make target pure-data/src/d_arithmetic.o* or *No such file or directory: pure-data/extra/bonk~/bonk~.c*.

So the clone has to bring the submodule with it:

bash
git clone --recurse-submodules https://github.com/libpd/libpd.git

After that you should have a `libpd` directory, and the `libpd/pure-data` directory should contain the pd sources. If your git version does not support `--recurse-submodules`, the fallback is to run the submodule commands inside the checkout:

bash
cd libpd
git submodule update --init --recursive

For most uses, the README recommends checking out the latest stable release version via a git tag, and it gives a concrete example of switching to version 0.8.3 after cloning:

bash
git checkout 0.8.3
git submodule update

Note the second command. After you move the tag, the submodule pointer has to be moved with it, and if you forget, you will be building the pd sources of a different version than the libpd wrapper you intended.

One line in the README is worth reading as the project's own position rather than as a caveat. The master branch contains the latest libpd development and can be considered generally stable, however no guarantees are made. The tone is informal and the statement is clear: there is no compatibility promise on master, and if you need reproducibility, use a tag.

Building the C core, then the wrappers around it

The core build requirements are a Unix command shell, bash or dash, and a C compiler chain, gcc or clang with make. The various language wrappers may have additional requirements.

The main Makefile builds a dynamic library on Windows in MinGW, on Linux and on macOS, and the targets are listed explicitly. `libpd` builds the libpd C core and is the default when no target is specified. `csharplib` builds libpdcsharp, and `javalib` builds libpdnative together with the JNI wrapper. `javadoc` generates the Java HTML documentation and `javasrc` creates a Java source jar. `clean` removes object files and `clobber` removes the linked library files. `install` and `uninstall` install and remove the libpd C library and the C and C++ headers, with the location set by the `prefix=` variable, which defaults to /usr/local.

The C++ headers are only installed if the C utility layers were built as well, meaning the `UTIL=true` option, and that option is on by default.

The minimal build is one command:

bash
make

And the build without the utility libraries and the extra externals is:

bash
make UTIL=false EXTRA=false

with the note that the C++ wrapper requires `UTIL=true` because it uses the ringbuffer. That dependency is worth knowing before you plan a build, because the natural first instinct, strip the library down to the minimum, produces a C++ wrapper that cannot link.

Once the build succeeds, the compiled libraries are in the `libs` directory. The `samples/` directory holds small sample programs and tests in the various supported languages, and there is a `samples/emscripten/` directory, which is the one to look at if you are compiling to the browser.

The Makefile options decide what is inside the library

The options list is the closest thing this project has to a specification, and each one changes the shape of the binary rather than just the build flags.

`UTIL=true` compiles the utilities in `libpd_wrapper/util` and is the default. `EXTRA=true` compiles the `pure-data/extra` externals, which are then initialised in `libpd_init()`, and is also the default. `MULTI=true` compiles with multiple instance support, which is what lets a host program create more than one independent Pd instance in one process. `DOUBLE=true` adds double-precision support. `DEBUG=true` compiles with debug symbols and no optimisations.

`STATIC=true` compiles a static library in addition to the shared one. `FAT_LIB=true` compiles a universal fat lib with multiple architectures, and the README marks this as macOS only. `LOCALE=false` does not set the LC_NUMERIC number format to the default C locale, which is also the default behaviour, and the README points at the Known Issues section for more on it. `PORTAUDIO=true` adds portaudio support, currently for the Java JNI path only. And `JAVA_HOME=/path/to/jdk` points the build at a Java Development Kit, which the macOS and Windows flag definitions use to locate the JNI headers.

The default configuration is therefore a fairly rich library: utilities in, extra externals in, single instance, single precision, shared object, with the host locale's number format left alone. If you want the leanest possible binary for an embedded device, `make UTIL=false EXTRA=false` is the starting point, and the catch is the C++ wrapper's ringbuffer requirement.

There is one more mechanism for customisation, and it is the one to reach for when you need a specific include or library path:

bash
make ADDITIONAL_CFLAGS="-I/usr/local/include" \
     ADDITIONAL_LDFLAGS="-L/usr/local/lib"

That is how you point the build at a third party dependency without editing the Makefile, which matters because the Makefile is shared and your changes to it are the ones you will have to re-apply on every update.

Cross-compiling for ARM, and the macOS universal build

On Linux and BSD you install the core build requirements with the distribution's package manager, and for Debian the README gives the compiler chain, autotools and gettext in one command:

bash
sudo apt install build-essentials

Cross-compiling is where the Makefile earns its keep. You need the additional packages and you set the `CC` environment variable for the target architecture, and the README gives three Debian examples.

For 32 bit Intel:

bash
sudo apt install gcc-i686-linux-gnu
make CC=i686-linux-gnu-gcc

For 32 bit ARM:

bash
sudo apt install gcc-arm-linux-gnueabi
make CC=arm-linux-gnueabi-gcc

And for 64 bit ARM:

bash
sudo apt install gcc-aarch64-linux-gnu
make CC=aarch64-linux-gnu-gcc

That third one matters for embedded Linux work, and the presence of a 32 bit ARM target alongside it says the project is used on hardware where the 64 bit toolchain is a choice rather than a default.

macOS has its own path, and the README starts with the platform fact that macOS is built on a BSD system, so the command line is reached through Terminal. For the compiler, if you are running macOS 10.9 or later you do not need the full Xcode application and can install the Commandline Tools Package alone:

bash
xcode-select --install

For older systems, macOS 10.6 to 10.8, you need Xcode from the Mac App Store or downloaded from Apple's developer site.

The fat library is the last piece, and it is version dependent. With `FAT_LIB=true`, the build produces a library for multiple architectures depending on the detected system version: i386 and x86_64 for macOS 10.13 and below, arm64 and x86_64 for macOS 11.0 and above. To override the autodetection, the `FAT_ARCHS` Makefile option takes the `-arch` flags directly.

The language bindings and the samples that show them

The glue directories in the tree are the practical face of the project. There is `cpp` for C++, `csharp` for C#, `java` and `jni` for the Java path, `objc` for Objective-C, and `python` for Python, and the README invites contributions to improve them or to add support for other languages such as Lua.

The build system files match that spread: `Android.mk` for Android, `Makefile` for the Unix build, `libpd.xcodeproj` for Xcode, `libpd_csharp.sln` for Visual Studio, plus `.classpath` and `.project` for the Eclipse based Java tooling. There is also a `libpd.podspec`, so the iOS integration is available through CocoaPods, and `mingw32_build_csharp.bat` and `mingw64_build_csharp.bat` for the Windows C# build. A `CMakeLists.txt` sits at the root alongside the Makefile, so a CMake based project is also a supported route.

The `samples/` directory holds small programs and tests in each supported language, with subdirectories for C, C++, C#, Java, Objective-C and Python, plus the Emscripten one. Those samples are the fastest way to see what a host program actually has to do, because a synthesis library is only useful if you can see the calling convention.

There are companion repositories for the environments where people usually meet Pure Data first: puredatap5 for Processing, pd-for-ios and pd-for-android. The README points at them for anyone using Processing, iOS or Android, which tells you the intended audience is application developers rather than audio researchers, who would use Pd itself.

The documentation lives in the project wiki rather than in the tree, and the repository also carries a `CHANGES.txt`, which is the file to read when you are tracking what changed between libpd versions.

Where libpd is the wrong choice

There are three situations where this library is the wrong tool, and they are all about what you are taking on.

The first is when you need a stable, packaged dependency. The repository has no GitHub releases, and while there are git tags such as 0.8.3, you get the source rather than a binary, and you are expected to compile it. For an application that ships to end users, building a C library with a submodule of someone else's C sources as part of your release process is a real cost, and one that the project does not hide.

The second is when you need a stable API. libpd wraps Pd Vanilla, and the wrapper is thin by design, so you are exposed to Pd's interfaces rather than insulated from them. When Pd changes, and Pd changes on its own schedule and its own versioning, your code is affected. The README's own statement that master can be considered generally stable with no guarantees is a fair description of the risk.

The third is when you do not actually need a patching environment. If you want to play a sound file, or trigger a fixed instrument, a sample player or a small sampler library is a fraction of the work. Pd's generality is the point, and it is also the reason the build needs a compiler chain, a submodule and a set of options.

The alternative approach, and the one to weigh against, is to use Pure Data itself as a separate process and talk to it. The difference in approach is that Pd gives you the whole environment, the editor, the patch library and the community, at the cost of a process boundary, an inter-process protocol and the loss of embedding. libpd gives you the engine in your address space, with the patch built in code, and the cost of the build system and the upstream coupling.

There is a third option worth naming for the iOS and Android cases, and the companion repositories are it: pd-for-ios and pd-for-android already package libpd for those platforms, so if your target is a phone, the honest advice is to start from those rather than to assemble the toolchain yourself.

Editorial conclusion

Adopt libpd if you want the Pure Data patching environment inside an application of your own, a game, a teaching tool, an installation, and you are prepared to build it from a git checkout, because the ZIP download is broken by design and the submodule is the whole point. Do not adopt it if you need a packaged binary release, since the repository publishes no GitHub releases and you must build from source, or if you need a stable API across versions, because you inherit Pd Vanilla's internals along with libpd's. Verify three things first: that you clone with the pure-data submodule, since a checkout without it cannot build, that the Makefile options you need are set before you build, particularly `EXTRA` and `UTIL` which are on by default and change what is inside the library, and that the language wrapper you intend to use is one of the ones the project actually ships glue for.

Frequently asked questions

What is libpd and what does it package?

It is Pure Data as an embeddable audio synthesis library. The pure-data directory holds the sources of Pd Vanilla and its standard externals as a git submodule, and libpd_wrapper holds the core of libpd itself, with glue for C++, C#, Java, Objective-C and Python.

How do I download libpd so that it actually builds?

Use git with submodules: `git clone --recurse-submodules https://github.com/libpd/libpd.git`. The README explicitly warns against downloading a zip or tar.gz from GitHub, because submodule files are not included and the build then fails with errors such as No rule to make target pure-data/src/d_arithmetic.o.

How do I build libpd and where do the libraries end up?

Run `make` for the default libpd C core build, with gcc or clang and a Unix shell as the core requirements. The compiled libraries are found in the libs directory, and `make UTIL=false EXTRA=false` builds without the utility libraries and the extra externals, though the C++ wrapper needs UTIL=true because it uses the ringbuffer.

How do I cross-compile libpd for an ARM device?

Install the target toolchain and set the CC variable, for example `sudo apt install gcc-arm-linux-gnueabi` with `make CC=arm-linux-gnueabi-gcc` for 32 bit ARM, or `gcc-aarch64-linux-gnu` with `make CC=aarch64-linux-gnu-gcc` for 64 bit ARM.

Does libpd have releases I can depend on?

The repository has no GitHub releases. The README recommends checking out the latest stable release version via a git tag, giving 0.8.3 as the example, and notes that the master branch contains the latest development and can be considered generally stable without any guarantee.

Official sources

  1. Issues
  2. libpd/libpd on GitHub
  3. README
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/libpd-libpd.svg)](https://hysenlabs.com/projects/libpd-libpd)

Was this useful?