Percupuff
A drum synthesizer written in Cmajor with a TypeScript/React UI. Creates semi-realistic drum sounds using various audio synthesis techniques. Educational focus, serves as an introduction to audio programming and enables experimentation. Can be compiled as CLAP/VST3 plugin, standalone executable, or WebAssembly.
Install / Use
/learn @lilyvanoekel/PercupuffREADME
Percupuff
Percupuff is a drum synthesizer† written in Cmajor with a TypeScript/React user interface. It aims to create semi-realistic drum sounds using a wide variety of audio synthesis† techniques, inspired by various articles (such as this one) and other sources.
Thanks to the Cmajor tooling, this project can be compiled as a plugin† to run in a DAW† (such as Reaper) as a CLAP† or VST3† plugin, as a standalone executable or as a WebAssembly†.
To control the synthesizer MIDI† input is typically used. It can be played real time with a MIDI controller†, or through a sequencer† in a DAW. Ideally at some point the web version will also be playable through PC keyboard, mouse, touch, etc. for a lower bar of entry and more fun.
This project aims to prioritize an "educational angle" over things like performance or ultra realistic sound. The hope is that it can serve as an introduction to this kind of "audio programming" and enable experimentation and collaboration.

So what is it?
Percupuff is a drum machine that creates drum sounds by building them from scratch using math and code. It can run on the web, as a standalone program, or as a plugin in your music software. Each drum sound is created using different techniques, making it great for learning how digital audio works or just making quirky drum sounds for your music.
Why would I want this?
- You produce music on the computer and want some new quirky drum sounds.
- You want to learn about audio programming and do some experiments. Play around with existing sounds or design your own.
- You want to connect a Drumpad or Keyboard and play in real time.
State of the Project
The project is currently not finished. Not all sounds and features have been implemented yet. Contributions are welcome. Please have a look at:
These resources could also be helpful:
If anything is still unclear after that, please feel free to create a question issue.
Demo / Web Version
Building and Running
The easiest way to get started is to use VSCode (or a similar IDE) with the Cmajor Tools extension. Please see the Cmajor Getting Started instructions.
Prerequisites
- VSCode
- Cmajor Tools extension
- Node.js 20.19+ or 22.12+ (required for Vite 7.x)
- npm
Quick Start
The fastest way to get the UI running for development:
- Navigate to the view folder:
cd view
- Install dependencies:
npm install
- Start the development server:
npm run dev
- Open your browser to http://localhost:5173/
This gives you hot reload for UI development. When you're ready to test with the full Cmajor patch, run npm run build and follow the Running instructions below.
Building the view
The view needs to be built before you can run the project or build/export it as a plugin or WebAssembly.
From the project root:
cd view
npm install
npm run build
This will create view/dist which will contain:
- The built view
- An
index.jsfile that functions as the glue between the Cmajor code and the view.
Running
In VSCode with the Cmajor Tools installed:
- Open
percupuff.cmajorpatch - Open the Command Palette:
- Command+Shift+P (on Mac) or
- Ctrl+Shift+P (on Windows/Linux)
- Select
Cmajor: Run patch.
Development
Cmajor makes this pretty easy and straightforward, but there are a few gotchas in this project to be aware of:
UI Development Workflow
You have two options for developing the UI:
Option 1: Independent UI Development (Recommended for UI work)
- Run
npm run devfrom theviewfolder - Open http://localhost:5173/ in your browser
- Changes hot reload automatically
- Great for working on the interface without needing the full Cmajor patch
Option 2: Testing with Cmajor
- Make your changes to the TypeScript/React code
- Run
npm run buildin theviewfolder - Use
Cmajor: Run patchto see your changes - The view does NOT hot reload in this mode
Cmajor/DSP Code
-
The Cmajor†/DSP† code hot reloads:
- While having
Cmajor: Run patchopen make changes to any cmajor file - Save them and they will be applied right away.
- While having
-
In
percupuff.cmajorpatchwe refer toview/dist/index.jsspecifically:- This means the view must be rebuilt with
npm run buildbefore changes appear inCmajor: Run patch - Hot reload only works for Cmajor/DSP code, not for the TypeScript/React view
- This also applies to any other Cmajor related tooling such as
Cmajor: Export patch as.... Always build the view first.
- This means the view must be rebuilt with
Parameters
-
Parameters† are defined in
view/src/params.ts:- This project uses a LOT of parameters.
- To reduce duplicated work
view/src/params.tsis considered the source of truth. - Parameters are also defined in
dsp/Params.cmajor, do not manually edit them here. - Instead use
npm run build-paramsfrom theviewfolder.- Currently you have to manually paste its output into
dsp/Params.cmajor. This should be made easier at some point.
- Currently you have to manually paste its output into
Grouped Parameters
-
Some parameters are grouped (skip this for now if it's confusing).
- Some of the sound processors† (the files under
dsp/drums) can create multiple sounds. - Parameters such as level†, panning† and velocity† currently apply to the whole group.
- For examples please see:
view/src/params.ts, specifically theparamToEndpointIdandendpointIdToParamsfunctions.view/src/commands/ParamBuilder.tsgetConsolidatedParams
- Some of the sound processors† (the files under
Troubleshooting
"Missing script: dev" error
Make sure you're in the view directory:
pwd # Should show .../percupuff/view
If you're in the project root, navigate to view:
cd view
Node.js version error
If you see "Vite requires Node.js version 20.19+ or 22.12+":
- Check your Node version:
node --version
- Upgrade Node.js:
- Download from https://nodejs.org/ (LTS version recommended)
- Or use nvm (Node Version Manager) to switch versions:
nvm install 22
nvm use 22
Changes not appearing in Cmajor patch
Make sure you've built the view after making changes:
cd view
npm run build
Building a CLAP plugin
Prerequisites:
- Cmajor extension in VSCode (or Cursor)
- The view has been built with the most recent changes (see Building the view)
- CMake
- macOS (these instructions are macOS-specific)
Steps:
-
Export the patch as a CLAP plugin:
- Open Command Palette:
Cmd+Shift+P - Select
"Cmajor: Export patch as a CLAP plugin"
- Open Command Palette:
-
Download the CLAP SDK:
- Download from: https://github.com/free-audio/clap
- Extract and store the CLAP SDK somewhere on your system
-
Build the plugin:
cd /path/to/exported/plugin/folder cmake -B build -DCLAP_INCLUDE_PATH="/path/to/clap/include" -DCMAKE_BUILD_TYPE=Release cmake --build build --config Release -
Install the plugin:
cp -r ./Percupuff.clap /Library/Audio/Plug-Ins/CLAP
General MIDI Percussion Key Map
General MIDI† defines a standard for percussive sounds that assigns specific notes to specific percussive instruments. In MIDI each note has a number. 60, for example, represents a C note at a certain octave. The percussion map defines which note numbers trigger which drum sounds, so instead of playing a tone, you get a specific percussion instrument.
This project attempts to follow this standard. Below is a table showing the state of what is implemented so far. Some instruments exist in the UI, but have no actual implementation yet.
Contributions for instruments that are not yet included in the UI are definitely welcome. They do come with the added complexity of needing to rejiggle the UI, but that does not necessarily have to be done in the same PR.
| Note | Instrument | Included in UI | Implemented | Source File | | ---- | ------------------ | -------------- | ----------- | --------------------------------------------- | | 35 | Acoustic Bass Drum | ✅ | ✅ | BassDrum.cmajor | | 36 | Electric Bass Drum | ✅ | ❌ | -
