Getting Started with JUCE on Windows

Coding up a simple audio plugin with JUCE - the leading framework for multi-platform audio applications.

Getting Started with JUCE on Windows

JUCE is a C++ library that can be used to develop your own audio plugins from scratch. If you are new to C++ and JUCE, coding up a plugin can be a daunting task. In this post we will go over how to set up a development environment on Windows and make a simple audio plugin using Microsoft Visual C++ (MSVC) and CMake.

We'll be making the simplest plugin in the book - a mute. (It just mutes your audio). Let's get started!

Install the MSVC compiler toolset

Microsoft Visual C++ (MSVC) can be downloaded from the Visual Studio downloads page. scroll down until you see Tools for Visual Studio 2019 under the All Downloads section and select the download for Build Tools for Visual Studio 2019. (Alternatively, you can download Visual Studio itself if you are planning to use the IDE)

This will launch the Visual Studio Installer, which will bring up a dialog showing the available workloads. Check the Desktop development with C++ workload and select Install.

Note that the installation doesn't add the compiler to the global system path. To use MSVC from a command line or VS Code, you must run from the Developer Command Prompt for Visual Studio. It's installed with the compiler and can be accessed from the start menu. To verify the installation, type 'cl' inside the Developer Command Prompt. You should see a copyright message with the version and basic usage description.

Download JUCE

You can find the JUCE library at https://github.com/juce-framework/JUCE. Download the repository as a .zip file or clone it into your PC.

Note that we are NOT using Projucer (JUCE's own project-configuration tool), but instead using CMake to setup the project. This gives us a better idea of what's happening.

Setup a new project

Open the Developer command prompt and navigate to the folder which you want to set up your project in. Open the folder with VS Code.

(Note: Opening VS Code from the start menu or a command prompt won't work because the necessary path environment variables not set)

cd C:/Code
mkdir mute-plugin
cd mute-plugin
code .

JUCE has provided us with some boilerplate code for CMake audio plugin projects. You can find it in in your JUCE download under JUCE\examples\CMake\AudioPlugin. Copy the contents of this folder into your project directory. You will also need to make a copy of the main JUCE folder inside your project. (You only need the extras and modules subfolders). Your file structure should look like this.

.
├── CMakeLists.txt
├── JUCE
│   ├── CMakeLists.txt
│   ├── extras
│   └── modules
├── PluginEditor.cpp
├── PluginEditor.h
├── PluginProcessor.cpp
└── PluginProcessor.h

Configure CMake

The CMakeLists.txt file specifies how your project is built. First, we need to tell CMake where the JUCE headers are located. We can either add the JUCE directory to our project or install JUCE globally on our system. We already copied in the JUCE directory into our project, so we need to tell CMake to add it by uncommenting the following line

add_subdirectory(JUCE)

Now you can go on to change other settings. The JUCE CMake API explains all the available settings. For our purposes we will only change some settings under juce_add_plugin()

juce_add_plugin(AudioPluginExample
    COPY_PLUGIN_AFTER_BUILD TRUE
    VST3_COPY_DIR C:/VST3
    PLUGIN_MANUFACTURER_CODE Juce
    PLUGIN_CODE Mute
    FORMATS VST3
    PRODUCT_NAME "Mute")

Here we have setup the project to build only the VST3 plugin and copy it to C:/VST3

Edit the source code

Now we need to make the plugin do something. The processing of the plugin is handled in processBlock(...) method of PluginProcessor.cpp, which we are going to edit. Delete the contents of the function and replace it with the following code.

void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
                                             juce::MidiBuffer &midiMessages) {
    auto *channeldata = buffer.getWritePointer(0);
    for (int i = 0; i < buffer.getNumSamples(); i++) {
        channeldata[i] = 0.0f;
    }
}

This code does the following:

  • Assigns a variable channeldata as the write pointer of the audio buffer. Selecting 0 in getWritePointer() will assign channeldata to the left input channel.
  • Iterates through the audio buffer and sets it to 0.

If you want to mute both channels the code should be modified as follows

void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
                                             juce::MidiBuffer &midiMessages) {
    auto *channeldataL = buffer.getWritePointer(0);
    auto *channeldataR = buffer.getWritePointer(1);
    for (int i = 0; i < buffer.getNumSamples(); i++) {
        channeldataL[i] = 0.0f;
        channeldataR[i] = 0.0f;
    }
}

Build the plugin

We can now go on and build the plugin. Execute the following commands in the root folder of your project

cmake -B cmake-build
cmake --build cmake-build

The plugin should build and get copied to C:/VST3 as we specified earlier. If you didn't set the copy plugin option, you can always see where the build was created in the command line output.

Test it in you DAW

Add the plugin to your DAW. Since we didn't specify a company name it should appear under yourcompany

Drag the plugin onto an audio track. The sound should be muted as you programmed. Turn off (bypass) the plugin and verify this.

Additional references