:#/ GSLF Journal
← :#/ GSLF Journal

01. Coding Sound in c++: audio plugin fundamentals

On this page

<figure class="video" style="margin:0;">
<div style="position:relative;width:100%;padding-bottom:56.25%;height:0;overflow:hidden;">
<iframe src="https://www.youtube.com/embed/xKhgPKhgbMs?si=BfSsw_gIPYgabqPF"
title="YouTube video player"
style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>
</div>
</figure>

In this lesson, we are going to establish the mental model required to be an audio developer. Developing audio plugins is significantly different from web development or standard application programming. It requires a specific understanding of how data flows through a computer in real-time.

Before we write code, we must understand the environment we are working in. A plugin (like a VST3 or AU) does not run by itself. It runs inside a Host. The Host is the DAW (e.g., Ableton Live, Logic Pro, Cubase).

The relationship works like this:

  1. The Host sends data to your plugin (MIDI notes, automation data, and audio buffers).
  2. Your Plugin processes this data mathematically.
  3. Your Plugin fills a buffer with new audio numbers.
  4. The Host takes those numbers and sends them to the sound card.

When we use the JUCE framework, this relationship is split into two distinct classes. You will see these file names immediately when we create our project:

  1. The Processor (PluginProcessor.cpp): This is the brain. It handles the math, the MIDI events, and the audio generation. It runs invisibly in the background.
  2. The Editor (PluginEditor.cpp): This is the face. It handles the graphics, the knobs, the sliders, and user mouse clicks.

The Audio Processor runs continuously, even if the GUI (Editor) is closed. The GUI is just a remote control for the Processor.

AUDIO THREAD#

The most important concept in this entire course is the Audio Thread. Audio is a stream of numbers. To play audio without "glitching" (clicks and pops), the computer must calculate these numbers faster than the speakers can play them. This calculation happens in a high-priority loop called the Audio Thread.

If your sample rate is 44,100 Hz and your buffer size is 128 samples, your plugin has approximately 2.9 milliseconds to calculate all the audio for that buffer. If you take 3.0 milliseconds, the audio driver runs out of data, and the speaker makes noise.

Therefore, inside the audio processing function, you are strictly forbidden from doing anything slow ("blocking"). This includes no memory allocation (never use new, malloc, or std::vector::resize), no file access (never read from a hard drive or load a preset file directly), no networking (never talk to a server), and no locking (avoid complex thread locks that might make the audio thread wait for the GUI thread). We will learn how to bypass these limitations using specific C++ patterns later in the course.

OUR GOALS#

To ensure we stay focused, here is the specification for the synthesizer we will build, serving as our development roadmap. We will be designing a polyphonic architecture capable of handling multiple notes at once. The project will target multiple formats, including VST3 and AU for macOS, as well as a completely Standalone Application.

The core of our sound generation will rely on two oscillators offering Saw, Square, and Sine waves, supplemented by a white noise generator and a mixer to blend the signals. This audio will then pass through a State-Variable Filter capable of switching between Lowpass, Bandpass, and Highpass modes.

To add movement and character to the sound, we will implement a modulation system featuring two ADSR envelopes (one for the amplifier and one for the filter) and a single LFO. We will also include an effects section comprised of a drive/distortion unit and a delay line. Finally, the instrument will feature a fully custom GUI with support for saving and loading presets.

In the next lesson, we will install the tools required to turn C++ code into a working plugin.