Getting Started with C++ JUCE: Building Your First VST Plugin
Audio plugins like VSTs are the backbone of digital music production. Creating one from scratch might sound daunting, but JUCE, a powerful C++ framework, makes it approachable for developers of all levels.
In this guide, we’ll introduce JUCE and walk through the process of creating a simple audio plugin.
What Is JUCE?
JUCE is a cross-platform C++ framework for building:
- Audio plugins (VST, AU, AAX)
- Standalone audio applications
- User interfaces for music software
It handles much of the low-level boilerplate, letting you focus on the creative aspects of audio processing.
Benefits of JUCE:
- Cross-platform: Windows, macOS, Linux
- Handles plugin formats automatically
- Provides GUI components for controls and sliders
- Built-in audio engine and MIDI support
Setting Up Your First Project
The recommended way to start a JUCE plugin is using Projucer, JUCE’s project management tool.
Steps:
- Download and install JUCE from the official website.
- Launch Projucer and create a New Project → Audio Plugin.
- Choose your project name, plugin formats (VST3, AU, etc.), and target platforms.
- Save the project and open it in your IDE (Visual Studio, Xcode, or CLion).
Projucer generates a ready-to-build skeleton:
PluginProcessor.cpp→ Handles audio processingPluginEditor.cpp→ Handles GUI and user interaction
Understanding the Project Structure
- PluginProcessor: The heart of your plugin. This is where you process audio and MIDI data.
- PluginEditor: The visual interface. Sliders, knobs, and buttons live here.
- JuceLibraryCode: All the necessary JUCE modules bundled into the project.
This separation ensures a clean workflow: audio logic in one place, GUI in another.
Writing Your First Audio Effect
Let’s create a simple gain plugin that multiplies the incoming audio signal by a factor.
- Open
PluginProcessor.cpp. - Locate the
processBlockmethod — this is called for every buffer of audio. - Multiply each sample by a gain factor:
for (int channel = 0; channel < totalNumInputChannels; ++channel)
{
auto* channelData = buffer.getWritePointer(channel);
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
channelData[sample] *= gain; // gain = 0.5, for example
}
This simple loop scales the audio volume by gain.
Adding a GUI Slider
Next, let’s connect a slider to control the gain in real time:
- In
PluginEditor.h, declare ajuce::Sliderobject. - In
PluginEditor.cpp, initialize and attach it to your plugin’s value tree or processor variable. - Use
slider.onValueChangeto update the gain inPluginProcessor.
JUCE makes this integration straightforward, so your GUI reflects the audio processing instantly.
Building and Testing
Once your code is in place:
- Build the project in your IDE.
- The result is a VST3 plugin file (or AU on Mac).
- Open your favorite DAW (Ableton, Logic, FL Studio, Reaper) and load the plugin.
- Test the slider and ensure the gain changes the output volume.
This immediate feedback loop is essential for plugin development.
Next Steps
After your first working plugin, you can explore:
- More audio effects: EQs, filters, distortion, reverb
- MIDI effects: Note generation, arpeggiators, modulations
- Advanced GUI: Custom sliders, meters, and graphics
- Presets and state saving: So users can save their settings
JUCE also provides tutorials, example projects, and a large community, which helps when tackling more complex effects.
Small Plugin, Big Learning
Even a simple gain plugin teaches you the core principles:
- Audio processing in C++
- Real-time control through GUI elements
- How VST/AU plugins interact with hosts
JUCE abstracts the repetitive work but still lets you get hands-on with the audio signal, making it an ideal framework for both beginners and advanced developers.
Once you’re comfortable with this workflow, the possibilities are endless — from virtual synths to multi-effect chains and beyond.