New to Plugin Development
Never built an audio plugin before? No problem. BeatConnect provides everything you need to go from zero to a professional, signed plugin.
What is an Audio Plugin?
Audio plugins are software that processes or generates audio within a DAW (Digital Audio Workstation) like:
- Ableton Live
- FL Studio
- Logic Pro
- Pro Tools
- Reaper
Plugins come in various formats:
| Format | Platform | Notes |
|---|---|---|
| VST3 | Windows, macOS | Most universal format |
| AU (Audio Units) | macOS only | Required for Logic Pro |
| AAX | Windows, macOS | Pro Tools only |
Learning Path
Week 1: Setup & First Build
- Check requirements
- Connect GitHub
- Clone the starter template
- Build your first (unchanged) plugin
- Install and test in your DAW
Week 2: Understanding the Code
- Explore the template structure
- Modify a parameter (gain, frequency)
- Rebuild and test changes
- Learn the audio processing basics
Week 3: Adding Features
- Add a new parameter
- Create a simple effect (tremolo, filter)
- Design a basic UI
- Build and distribute to friends
Week 4+: Going Professional
- Add license activation
- Create product listing
- Set up marketing
- Launch and sell!
Using the Starter Template
Clone the Template
# Clone the BeatConnect plugin template
git clone https://github.com/beatconnect/plugin-template my-first-plugin
cd my-first-plugin
# Remove the template's git history
rm -rf .git
# Initialize your own repo
git init
git add .
git commit -m "Initial commit from BeatConnect template"
# Push to your GitHub
gh repo create my-first-plugin --private --source=. --pushTemplate Structure
my-first-plugin/
├── CMakeLists.txt # Build configuration
├── src/
│ ├── PluginProcessor.h # Audio processing logic
│ ├── PluginProcessor.cpp
│ ├── PluginEditor.h # UI/interface
│ └── PluginEditor.cpp
├── external/
│ └── JUCE/ # JUCE framework (submodule)
├── resources/
│ └── logo.png # Plugin icon
└── README.md
Key Files Explained
PluginProcessor.cpp
This is where the magic happens. The processBlock function receives audio and processes it:
void MyPluginAudioProcessor::processBlock(AudioBuffer<float>& buffer,
MidiBuffer& midiMessages)
{
// Get the gain parameter value
float gain = *parameters.getRawParameterValue("gain");
// Apply gain to all samples
for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
{
float* channelData = buffer.getWritePointer(channel);
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
{
channelData[sample] *= gain;
}
}
}PluginEditor.cpp
This creates the user interface:
MyPluginAudioProcessorEditor::MyPluginAudioProcessorEditor(MyPluginAudioProcessor& p)
: AudioProcessorEditor(&p), processor(p)
{
// Create a slider for the gain parameter
gainSlider.setSliderStyle(Slider::RotaryVerticalDrag);
gainSlider.setTextBoxStyle(Slider::TextBoxBelow, false, 80, 20);
addAndMakeVisible(gainSlider);
// Connect the slider to the parameter
gainAttachment = std::make_unique<AudioProcessorValueTreeState::SliderAttachment>(
processor.apvts, "gain", gainSlider);
setSize(400, 300);
}AI-Assisted Development
BeatConnect integrates AI tools to help you learn and build faster.
Code Generation
Use AI to scaffold new features:
"Add a low-pass filter with cutoff and resonance parameters"
// AI generates:
// - Parameter definitions
// - DSP processing code
// - UI components
// - CMake configuration updates
Code Explanation
Understand existing code:
"Explain what this processBlock function does"
// AI explains:
// - What each line does
// - Why it's structured this way
// - Common modifications
Debugging Help
Fix issues faster:
"My plugin crackles at high sample rates"
// AI suggests:
// - Buffer size checks
// - Denormal prevention
// - Processing optimization
Important: AI is a tool, not a replacement for learning. Use it to accelerate understanding, not to blindly copy code you don’t understand.
Essential Concepts
Parameters
Parameters are values the user can adjust:
// Define parameters
parameters.createAndAddParameter(
"gain", // ID
"Gain", // Name
"", // Label
NormalisableRange<float>(0.0f, 2.0f, 0.01f), // Range
1.0f, // Default
nullptr, // Value to text
nullptr // Text to value
);Audio Buffers
Audio comes in buffers (arrays of samples):
// Buffer info
int numChannels = buffer.getNumChannels(); // Usually 2 (stereo)
int numSamples = buffer.getNumSamples(); // Usually 64-512
// Access samples
float sample = buffer.getSample(channel, sampleIndex);Sample Rate
The number of samples per second:
- 44,100 Hz — CD quality
- 48,000 Hz — Video standard
- 96,000 Hz — High resolution
Your code must work at any sample rate:
void prepareToPlay(double sampleRate, int samplesPerBlock)
{
// Store sample rate for calculations
this->sampleRate = sampleRate;
// Calculate time-based values
float delaySeconds = 0.5f;
int delaySamples = (int)(delaySeconds * sampleRate);
}Common Beginner Mistakes
1. Dividing by Zero
// BAD
float normalized = value / maxValue; // Crashes if maxValue is 0
// GOOD
float normalized = maxValue > 0 ? value / maxValue : 0.0f;2. Forgetting to Handle Stereo
// BAD - Only processes first channel
buffer.getWritePointer(0);
// GOOD - Process all channels
for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
{
float* channelData = buffer.getWritePointer(ch);
// Process...
}3. Denormal Numbers
Very small numbers can cause CPU spikes:
// Add to processBlock
for (int ch = 0; ch < numChannels; ++ch)
{
FloatVectorOperations::add(buffer.getWritePointer(ch),
1.0e-15f, // Tiny DC offset
numSamples);
}4. Not Saving State
Your parameters should persist when the DAW project is saved:
// Override these methods
void getStateInformation(MemoryBlock& destData)
{
auto state = parameters.copyState();
std::unique_ptr<XmlElement> xml(state.createXml());
copyXmlToBinary(*xml, destData);
}
void setStateInformation(const void* data, int sizeInBytes)
{
std::unique_ptr<XmlElement> xml(getXmlFromBinary(data, sizeInBytes));
if (xml.get() != nullptr)
parameters.replaceState(ValueTree::fromXml(*xml));
}Resources for Learning
Official Documentation
YouTube Channels
- The Audio Programmer — Beginner-friendly JUCE tutorials
- ADC (Audio Developer Conference) — Deep technical talks
- Akash Murthy — DSP and plugin development
Communities
Books
- Designing Audio Effect Plugins in C++ — Will Pirkle
- DAFX: Digital Audio Effects — Udo Zölzer
- The Audio Programming Book — Richard Boulanger
Your First Real Effect: Tremolo
Let’s build a simple tremolo effect (volume modulation):
class TremoloProcessor : public AudioProcessor
{
private:
float phase = 0.0f;
float rate = 5.0f; // Hz
float depth = 0.5f; // 0-1
public:
void processBlock(AudioBuffer<float>& buffer, MidiBuffer&)
{
float phaseIncrement = rate / getSampleRate();
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
{
// Calculate LFO value (sine wave)
float lfo = 0.5f + 0.5f * std::sin(2.0f * MathConstants<float>::pi * phase);
// Apply depth
float modulation = 1.0f - depth + (depth * lfo);
// Apply to all channels
for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
{
buffer.getWritePointer(ch)[sample] *= modulation;
}
// Advance phase
phase += phaseIncrement;
if (phase >= 1.0f) phase -= 1.0f;
}
}
};Next Steps
- Build your first plugin
- Experiment with the template
- Join the Discord community for help
- Share your creations!
Remember: Every professional plugin developer started exactly where you are now. The key is to start simple, build consistently, and never stop learning.